Skip to content

Commit 10a945d

Browse files
committed
doc: update README, add design and contribution markdown documents
Signed-off-by: Valentin Daviot <valentin.daviot@scality.com>
1 parent b34fb24 commit 10a945d

3 files changed

Lines changed: 303 additions & 58 deletions

File tree

CONTRIBUTING.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Contributing
2+
3+
Thank you for your interest in contributing to RAIDmgmt! Here are some
4+
guidelines to help you get started.
5+
6+
## Getting Started
7+
8+
1. Fork the repository and clone your fork.
9+
2. Make sure you have Go 1.25+ and [golangci-lint](https://golangci-lint.run/)
10+
installed.
11+
12+
## Making Changes
13+
14+
1. Create a branch for your work.
15+
2. Keep commits focused -- one logical change per commit.
16+
3. Follow the existing code style. The project uses `golangci-lint` with the
17+
configuration in `.golangci.yaml`.
18+
4. Add or update tests for any changed behavior.
19+
5. Run `make all` before submitting your changes.
20+
21+
## Adding a New RAID Controller
22+
23+
The library is designed to be extended with new controllers. To add one:
24+
25+
1. Create a new package under `pkg/implementation/` for any low-level CLI
26+
interactions (command runners, getters, managers).
27+
2. Implement the port interfaces defined in `pkg/domain/ports/raidcontroller.go`.
28+
If your controller does not support a given operation, return
29+
`ports.ErrFunctionNotSupportedByImplementation`.
30+
3. Create a composite adapter under `pkg/implementation/raidcontroller/` that
31+
wires the individual implementations together (see `rhel8.go` or
32+
`smartarray.go` for examples).
33+
4. Add unit tests with testdata fixtures.
34+
35+
## Pull Requests
36+
37+
1. Open a pull request against the `main` branch.
38+
2. Describe what your change does and why.
39+
3. Make sure CI checks pass (lint + tests).
40+
41+
## Reporting Issues
42+
43+
Open a GitHub issue with a clear description of the problem or feature request.
44+
Include steps to reproduce if applicable.

DESIGN.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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.

README.md

Lines changed: 98 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,116 @@
11
# RAIDmgmt
22

3-
RAIDmgmt is a Go library for managing RAID configurations on various RAID controllers.
4-
It provides an abstraction layer for interacting with different RAID controllers and software RAID setups, allowing users to perform RAID operations in a consistent way across different environments.
5-
6-
It follows the [Hexagonal architecture](https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)) to easily integrate new RAID controllers.
3+
RAIDmgmt is a Go library for managing RAID configurations across hardware and
4+
software RAID controllers. It provides a unified abstraction layer so consumers
5+
can perform RAID operations consistently, regardless of the underlying
6+
controller.
77

88
## Features
99

10-
- Supports MegaRAID, PERC, Smart Array, and software RAID on RHEL8 based OSes.
11-
- Provides abstraction over RAID configuration and operations.
12-
- Extensible with support for additional RAID controllers via adapters.
10+
- **Hardware RAID** -- MegaRAID, Dell PERC, and HPE Smart Array controllers.
11+
- **Software RAID** -- `mdadm`-based RAID on RHEL8-family systems.
12+
- **Unified interface** -- A single set of ports covers controller listing,
13+
physical drive and logical volume management, cache options, JBOD, and drive
14+
identification blinking.
15+
- **Extensible** -- New controllers can be added by implementing the adapter
16+
interfaces.
1317

14-
## Usage
18+
## Installation
1519

16-
### Basic Example
20+
```bash
21+
go get github.com/scality/raidmgmt
22+
```
1723

18-
TODO
24+
## Quick Start
25+
26+
```go
27+
package main
28+
29+
import (
30+
"fmt"
31+
"log"
1932

20-
## Architecture
33+
"github.com/scality/raidmgmt/pkg/core"
34+
"github.com/scality/raidmgmt/pkg/implementation/commandrunner"
35+
"github.com/scality/raidmgmt/pkg/implementation/logicalvolumegetter"
36+
"github.com/scality/raidmgmt/pkg/implementation/logicalvolumemanager"
37+
"github.com/scality/raidmgmt/pkg/implementation/physicaldrivegetter"
38+
"github.com/scality/raidmgmt/pkg/implementation/raidcontroller"
39+
)
2140

22-
This library is designed with Hexagonal Architecture, which separates the core business logic (domain layer) from the system-specific implementations (adapters).
41+
func main() {
42+
// Create an RHEL8 software RAID controller
43+
runner := commandrunner.New()
44+
rc := raidcontroller.NewRHEL8(
45+
physicaldrivegetter.NewRHEL8(runner),
46+
logicalvolumegetter.NewMDADM(runner),
47+
logicalvolumemanager.NewMDADM(runner),
48+
)
49+
50+
// Wrap it with the core service for input validation
51+
svc := core.NewRAIDController(rc)
52+
53+
// List logical volumes (nil metadata for software RAID)
54+
volumes, err := svc.LogicalVolumes(nil)
55+
if err != nil {
56+
log.Fatal(err)
57+
}
58+
59+
for _, lv := range volumes {
60+
fmt.Printf("Volume %s: %s (%s)\n", lv.ID, lv.DevicePath, lv.RAIDLevel)
61+
}
62+
}
63+
```
2364

24-
- Core Domain: Contains core RAID logic and domain models.
25-
- Ports: Defines the interfaces for interacting with RAID controllers.
26-
- Adapters: Implementations of RAID interactions for specific controllers (e.g., MegaRAID, Smart Array).
65+
> **Note:** The example above is for software RAID. For hardware RAID
66+
> controllers (MegaRAID, Smart Array), see the adapter constructors in
67+
> `pkg/implementation/raidcontroller/`.
2768
28-
The repo is structured as it follows:
69+
## Project Structure
2970

3071
```
31-
├── go.work
32-
├── Makefile
33-
├── pkg
34-
│ ├── core
35-
│ │ ├── go.mod
36-
│ │ ├── go.sum
37-
│ │ └── raidcontroller.go
38-
│ ├── domain
39-
│ │ ├── entities
40-
│ │ │ ├── logicalvolume
41-
│ │ │ │ ├── enums.go
42-
│ │ │ │ ├── errors.go
43-
│ │ │ │ ├── methods.go
44-
│ │ │ │ └── types.go
45-
│ │ │ ├── physicaldrive
46-
│ │ │ │ ├── enums.go
47-
│ │ │ │ ├── errors.go
48-
│ │ │ │ ├── methods.go
49-
│ │ │ │ └── types.go
50-
│ │ │ └── raidcontroller
51-
│ │ │ ├── errors.go
52-
│ │ │ ├── methods.go
53-
│ │ │ └── types.go
54-
│ │ ├── go.mod
55-
│ │ └── ports
56-
│ │ └── raidcontroller.go
57-
│ └── impl
58-
│ └── raidcontroller
59-
│ ├── megaraid
60-
│ │ ├── go.mod
61-
│ │ ├── go.sum
62-
│ │ ├── storcli.go
63-
│ ├── rhel8
64-
│ │ ├── go.mod
65-
│ │ └── mdadm.go
66-
│ └── smartarray
67-
│ ├── go.mod
68-
│ └── ssacli.go
69-
└── README.md
72+
pkg/
73+
├── core/ # Core service (validation + delegation)
74+
├── domain/
75+
│ ├── entities/
76+
│ │ ├── logicalvolume/ # LogicalVolume entity, enums, methods
77+
│ │ ├── physicaldrive/ # PhysicalDrive entity, enums, methods
78+
│ │ └── raidcontroller/ # RAIDController entity
79+
│ └── ports/ # Port interfaces
80+
├── implementation/
81+
│ ├── blinker/ # Drive blinking adapters
82+
│ ├── commandrunner/ # CLI tool wrappers (storcli, ssacli, mdadm, ...)
83+
│ ├── controllergetter/ # Controller listing adapters
84+
│ ├── logicalvolumegetter/ # Logical volume listing adapters
85+
│ ├── logicalvolumemanager/ # Logical volume CRUD adapters
86+
│ ├── physicaldrivegetter/ # Physical drive listing adapters
87+
│ └── raidcontroller/ # Full RAIDController adapter compositions
88+
│ └── megaraid/ # MegaRAID/PERC-specific implementation
89+
└── utils/ # Shared utilities
7090
```
7191

72-
**Core** (`pkg/core/`): This is where the core business logic resides, such as the orchestration of RAID management tasks through the `raidcontrollerservice.go`. This part of the code should be agnostic to the specific RAID controller being used.
92+
See [DESIGN.md](DESIGN.md) for a detailed description of the architecture,
93+
entities, ports, and adapters.
7394

74-
**Domain** (`pkg/domain/`): This contains both the **ports** (interfaces that define how the core interacts with the outside world) and **models** (representations of domain entities like `LogicalVolume`, `PhysicalVolume`, and `RaidController`).
95+
## Development
7596

76-
**Impl** (`pkg/impl/`): This holds the **adapters** for the different RAID controllers (MegaRAID, PERC, SmartArray, etc.). These adapters implement the ports defined in `pkg/domain/` and are responsible for the actual interaction with the respective CLI tools or system-level commands for each RAID controller.
97+
### Prerequisites
98+
99+
- Go 1.25+
100+
- [golangci-lint](https://golangci-lint.run/)
101+
102+
### Commands
103+
104+
```bash
105+
make lint # Run linters
106+
make tests # Run unit tests
107+
make all # Run both
108+
```
109+
110+
## Contributing
111+
112+
See [CONTRIBUTING.md](CONTRIBUTING.md).
113+
114+
## License
115+
116+
TODO

0 commit comments

Comments
 (0)