|
| 1 | +# Design |
| 2 | + |
| 3 | +## Scope |
| 4 | + |
| 5 | +This library abstracts RAID configuration and provides a unified interface to |
| 6 | +interact with various hardware RAID controllers and software RAID setups. |
| 7 | + |
| 8 | +It does **not** contain any higher-level decision logic about _what_ RAID |
| 9 | +operations should be performed in specific scenarios. It only provides the |
| 10 | +building blocks to execute them. |
| 11 | + |
| 12 | +## Architecture |
| 13 | + |
| 14 | +The library follows [Hexagonal Architecture](https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)) |
| 15 | +with three main concepts: |
| 16 | + |
| 17 | +- **Entity** -- A representation of a physical or logical resource. |
| 18 | +- **Port** -- An abstract interface describing operations on resources. |
| 19 | +- **Adapter** -- A concrete implementation of a Port for a specific controller type. |
| 20 | + |
| 21 | +### Entities |
| 22 | + |
| 23 | +#### `RAIDController` |
| 24 | + |
| 25 | +Represents a RAID controller card. |
| 26 | + |
| 27 | +```go |
| 28 | +type RAIDController struct { |
| 29 | + *Metadata |
| 30 | + |
| 31 | + Name string // Name of the RAID controller card |
| 32 | + Serial string // Serial number of the RAID controller card |
| 33 | + IsJBODSupported bool // Can the controller be set in JBOD mode |
| 34 | + IsJBODEnabled bool // Is the controller currently in JBOD mode |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +#### `PhysicalDrive` |
| 39 | + |
| 40 | +Represents a physical drive (disk). |
| 41 | + |
| 42 | +```go |
| 43 | +type DiskType uint8 // Unknown, HDD, SSD, NVMe |
| 44 | +type PDStatus uint8 // Unknown, Used, UnassignedGood, UnassignedBad, Failed |
| 45 | + |
| 46 | +type Slot struct { |
| 47 | + Port string // Port number (if available) |
| 48 | + Enclosure string // Enclosure number (if available) |
| 49 | + Bay string // Bay number (if available) |
| 50 | +} |
| 51 | + |
| 52 | +type PhysicalDrive struct { |
| 53 | + *Metadata |
| 54 | + |
| 55 | + Slot *Slot |
| 56 | + Vendor string |
| 57 | + Model string |
| 58 | + Serial string |
| 59 | + WWN string // World Wide Name |
| 60 | + Size uint64 // Size in bytes |
| 61 | + Type DiskType // HDD, SSD, NVMe |
| 62 | + JBOD bool // Is the disk in JBOD mode |
| 63 | + Status PDStatus |
| 64 | + Reason string // Reason for the current status |
| 65 | + DevicePath string // e.g. /dev/sda |
| 66 | + PermanentPath string // e.g. /dev/disk/by-id/... |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +#### `LogicalVolume` |
| 71 | + |
| 72 | +Represents a logical volume (RAID array). |
| 73 | + |
| 74 | +```go |
| 75 | +type RAIDLevel uint8 // Unknown, RAID0, RAID1, RAID10 |
| 76 | +type LVStatus uint8 // Unknown, Optimal, Degraded, Failed |
| 77 | + |
| 78 | +type CacheOptions struct { |
| 79 | + ReadPolicy ReadPolicy // ReadAhead, NoReadAhead |
| 80 | + WritePolicy WritePolicy // WriteBack, WriteThrough, AlwaysWriteBack |
| 81 | + IOPolicy IOPolicy // Direct, Cached |
| 82 | +} |
| 83 | + |
| 84 | +type LogicalVolume struct { |
| 85 | + *Metadata |
| 86 | + |
| 87 | + PermanentPath string |
| 88 | + DevicePath string |
| 89 | + RAIDLevel RAIDLevel |
| 90 | + PDrivesMetadata []*physicaldrive.Metadata |
| 91 | + CacheOptions *CacheOptions |
| 92 | + Status LVStatus |
| 93 | + Reason string |
| 94 | + Size uint64 |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +### Ports |
| 99 | + |
| 100 | +The main port is `RAIDController`, which composes several fine-grained interfaces: |
| 101 | + |
| 102 | +| Interface | Responsibility | |
| 103 | +|---|---| |
| 104 | +| `ControllersGetter` | List and get RAID controllers | |
| 105 | +| `PhysicalDrivesGetter` | List and get physical drives | |
| 106 | +| `LogicalVolumesGetter` | List and get logical volumes | |
| 107 | +| `LogicalVolumesManager` | Create, delete, and modify logical volumes | |
| 108 | +| `LVCacheSetter` | Set cache options on logical volumes | |
| 109 | +| `JBODSetter` | Enable/disable JBOD mode on physical drives | |
| 110 | +| `Blinker` | Start/stop drive identification blinking | |
| 111 | + |
| 112 | +Not all adapters support every operation. Unsupported operations return |
| 113 | +`ErrFunctionNotSupportedByImplementation`. |
| 114 | + |
| 115 | +### Adapters |
| 116 | + |
| 117 | +#### MegaRAID / PERC |
| 118 | + |
| 119 | +Adapter for Broadcom MegaRAID and Dell PERC controllers. Interacts with |
| 120 | +hardware via `storcli`/`perccli`, which provides JSON output for easy parsing. |
| 121 | + |
| 122 | +Supports all port operations: controller listing, physical drives, logical |
| 123 | +volumes (CRUD), cache options, JBOD, and drive blinking. |
| 124 | + |
| 125 | +> **Note:** The current MegaRAID implementation (`pkg/implementation/raidcontroller/megaraid/`) |
| 126 | +> is a monolithic package that predates the decomposed architecture used by the |
| 127 | +> Smart Array and RHEL8 adapters. It is planned for refactoring to follow the |
| 128 | +> same pattern -- splitting into separate `commandrunner`, `controllergetter`, |
| 129 | +> `physicaldrivegetter`, `logicalvolumegetter`, and `logicalvolumemanager` |
| 130 | +> packages, and composing them in a top-level adapter. |
| 131 | +
|
| 132 | +#### Smart Array |
| 133 | + |
| 134 | +Adapter for HPE Smart Array controllers. Interacts with hardware via `ssacli`. |
| 135 | +Unlike `storcli`, this tool does not support JSON output, so responses are |
| 136 | +parsed using regular expressions. |
| 137 | + |
| 138 | +Supports all port operations. |
| 139 | + |
| 140 | +#### Software RAID (RHEL8) |
| 141 | + |
| 142 | +Adapter for `mdadm`-based software RAID on RHEL8-family systems. |
| 143 | + |
| 144 | +Uses `mdadm`, `lsblk`, `udevadm`, and `smartctl` to gather information and |
| 145 | +manage arrays. |
| 146 | + |
| 147 | +This adapter has the following limitations compared to hardware RAID: |
| 148 | + |
| 149 | +- No cache options. |
| 150 | +- No drive blinking. |
| 151 | +- No RAID 0 single-disk arrays. |
| 152 | +- No JBOD mode. |
| 153 | +- The `RAIDController` entity is not applicable (there is no hardware controller). |
| 154 | +- Partitions may be used as members of an array. Each partition is represented |
| 155 | + as a `PhysicalDrive`, but this library does not manage partitions themselves. |
| 156 | + |
| 157 | +## Core Service |
| 158 | + |
| 159 | +The `core.RAIDController` wraps any adapter and adds input validation before |
| 160 | +delegating to the underlying implementation. This is the recommended entry |
| 161 | +point for consumers of the library. |
0 commit comments