Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 73 additions & 3 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,11 @@ Not all adapters support every operation. Unsupported operations return

### Adapters

#### MegaRAID / PERC
#### MegaRAID / PERC (storcli, perccli)

Adapter for Broadcom MegaRAID and Dell PERC controllers. Interacts with
hardware via `storcli`/`perccli`, which provides JSON output for easy parsing.
Adapter for Broadcom MegaRAID and Dell PERC controllers up to the SAS3.5
generation (MegaRAID 94xx/95xx). Interacts with hardware via
`storcli`/`perccli`, which provides JSON output for easy parsing.

Supports all port operations: controller listing, physical drives, logical
volumes (CRUD), cache options, JBOD, and drive blinking.
Expand All @@ -129,6 +130,75 @@ volumes (CRUD), cache options, JBOD, and drive blinking.
> `physicaldrivegetter`, `logicalvolumegetter`, and `logicalvolumemanager`
> packages, and composing them in a top-level adapter.

#### MegaRAID 96xx / PERC 12 (storcli2, perccli2)

Adapter for the SAS4 ("MegaRAID 8" / tri-mode) generation: Broadcom MegaRAID
96xx and Dell PERC 12 controllers, driven through `storcli2`/`perccli2`.

It is built directly on the decomposed pattern: one component package per
port (`controllergetter`, `physicaldrivegetter`, `logicalvolumegetter`, ...),
each named `StorCLI2` and taking a `commandrunner.CommandRunner`. Both
binaries emit the same JSON schema, so a single set of components serves
both; the concrete runner (`commandrunner.StorCLI2` or
`commandrunner.PercCLI2`) is injected at construction time.

Design notes, verified against the StorCLI2 User Guide and a live MegaRAID
9660-16i:

- All outputs share a JSON envelope decoded by `pkg/implementation/storcli2.Decode`.
The process exit code is **not** a reliable success signal (some failures
exit 0, others exit non-zero while still writing the JSON payload), so
errors are detected from each controller's `Command Status` instead, and
the runners return the payload as-is on a non-zero exit.
- Showing a nonexistent object may report success with an absent section
(treated as an empty inventory) or an explicit failure payload: the User
Guide documents the former, while the binaries tested so far do the
latter. Both are handled.
- storcli2 has no controller-level JBOD enable and no JBOD personality.
`IsJBODSupported` is derived from a usable `JBOD` Advanced Software Option
(`show aso`) and `IsJBODEnabled` from the primary auto-configure behavior
(`show autoconfig`); JBOD itself is a per-drive **state**, orthogonal to
the per-drive **status** (each `set` command changes only one of the two).
- Drive states come in suffixed variants (`Shld`, `Sntz`, `Dgrd`), so they
are matched by family; a `Failed`/`Offline`/`Missing` status takes
precedence over any state.
- storcli2 dropped some storcli operations: there is no RAID-level migration
(drive *removal* from a volume is not possible; adding drives goes through
`/cx/vx expand drives=`), and no IO policy (`Cached`/`Direct`) cache
option -- the IO policy of parsed volumes is always `Unknown`.

The read path (controller, physical drive and logical volume getters), the
shared envelope/decoder and both command runners are implemented. The
remaining ports follow the same component pattern; the table below maps each
port operation to its storcli2 command (verified against the StorCLI2 User
Guide, the official storcli-to-storcli2 command map of the MegaRAID 8
software guide, and the binary's own help -- the grammar differs from
storcli in several places).

| Port operation | storcli2 command | Notes |
|---|---|---|
| `CreateLV` | `/cx add vd r<level> [Size=<sz>] drives=e:s,... [WT\|WB\|AWB] [nora\|ra]` | Cache policies are bare tokens at creation time; storcli's `type=` / `wrcache=` / `rdpolicy=` forms are gone. |
| `DeleteLV` | `/cx/vx delete [discardcache] [force]` | A nonexistent VD yields a failure payload surfaced by `Decode`. |
| `AddPDsToLV` | `/cx/vx expand drives=e:s,...` | Online capacity expansion. Documented and present in the binary help, but not exercised on hardware yet; progress is visible through `/cx/vx show expansion` and `show ocedriveinfo`. |
| `DeletePDsFromLV` | -- | Not supported: the official command map drops `start migrate` with no replacement for `option=remove`. Must return `ErrFunctionNotSupportedByImplementation`. |
| `SetLVCacheOptions` | `/cx/vx set rdcache=RA\|NoRA` and `/cx/vx set wrcache=WT\|WB\|AWB` | Two separate commands: storcli's combined syntax is rejected. The IO policy cannot be set (see above); beware that `CacheOptions.Validate()` rejects an unknown IO policy, so a request cannot be round-tripped from getter output as-is. |
| `EnableJBOD` | `/cx/ex/sx set jbod [force]` | Converts the drive **state**; the drive status is unchanged. |
| `DisableJBOD` | `/cx/ex/sx set uconf [force]` | storcli's `delete jbod` no longer parses; `set good` would only change the status. |
| `StartBlink` / `StopBlink` | `/cx/ex/sx start locate` / `stop locate` | Same grammar as storcli. |

Once every port is covered, a top-level `raidcontroller.StorCLI2` composition
embeds the seven components (no stubs: every operation except
`DeletePDsFromLV` is supported); a single composition serves both binaries
since only the injected runner differs. Until then the components are wired
individually.

> **Note:** Part of the pre-staged write-path fixtures under
> `pkg/implementation/logicalvolumemanager/testdata/storcli2/` and
> `pkg/implementation/physicaldrivegetter/testdata/storcli2/jbod/` were
> captured with the storcli grammar and are plain-text syntax errors; they
> must be regenerated with the commands above using
> `tests/testdata-tools/collect_storcli2_testdata.sh` (DESTRUCTIVE mode).

#### Smart Array

Adapter for HPE Smart Array controllers. Interacts with hardware via `ssacli`.
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ setup.

## Features

- **Hardware RAID** -- MegaRAID, Dell PERC, and HPE Smart Array controllers.
- **Hardware RAID** -- MegaRAID and Dell PERC controllers, including the SAS4
generation (MegaRAID 96xx / PERC 12 via `storcli2`/`perccli2`), and HPE
Smart Array controllers.
- **Software RAID** -- `mdadm`-based RAID on RHEL8-family systems.
- **Unified interface** -- A single set of ports covers controller listing,
physical drive and logical volume management, cache options, JBOD, and drive
Expand Down Expand Up @@ -78,7 +80,10 @@ func main() {

> **Note:** The example above is for software RAID. For hardware RAID
> controllers (MegaRAID, Smart Array), see the adapter constructors in
> `pkg/implementation/raidcontroller/`.
> `pkg/implementation/raidcontroller/`. A `raidcontroller.StorCLI2`
> composition for the MegaRAID 96xx / PERC 12 generation will join them once
> the storcli2 write path lands; until then the storcli2 components are wired
> individually.

## Project Structure

Expand All @@ -93,13 +98,14 @@ pkg/
│ └── ports/ # Port interfaces
├── implementation/
│ ├── blinker/ # Drive blinking adapters
│ ├── commandrunner/ # CLI tool wrappers (storcli, ssacli, mdadm, ...)
│ ├── commandrunner/ # CLI tool wrappers (storcli2, ssacli, mdadm, ...)
│ ├── controllergetter/ # Controller listing adapters
│ ├── logicalvolumegetter/ # Logical volume listing adapters
│ ├── logicalvolumemanager/ # Logical volume CRUD adapters
│ ├── physicaldrivegetter/ # Physical drive listing adapters
│ └── raidcontroller/ # Full RAIDController adapter compositions
│ └── megaraid/ # MegaRAID/PERC-specific implementation
│ ├── raidcontroller/ # Full RAIDController adapter compositions
│ │ └── megaraid/ # MegaRAID/PERC (storcli, perccli) implementation
│ └── storcli2/ # storcli2/perccli2 shared JSON envelope + decoder
└── utils/ # Shared utilities
```

Expand Down