Skip to content

Commit

Permalink
Merge pull request #130 from raharper/feat/add-raid-controller-interf…
Browse files Browse the repository at this point in the history
…ace-v2

Add support for smartpqi
  • Loading branch information
raharper authored Feb 16, 2024
2 parents 82804d0 + eabe011 commit 7c6624f
Show file tree
Hide file tree
Showing 17 changed files with 2,179 additions and 130 deletions.
11 changes: 0 additions & 11 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
linters-settings:
wsl:
allow-cuddle-declarations: true
funlen:
lines: 80
statements: 60

linters:
# you can see what is disabled with: golangci-lint linters
enable:
- bodyclose
- depguard
- dogsled
- dupl
- errcheck
- exhaustive
- exportloopref
- funlen
- gochecknoglobals
- gochecknoinits
- goconst
Expand All @@ -27,7 +18,6 @@ linters:
- gosimple
- govet
- ineffassign
- lll
- misspell
- nakedret
- noctx
Expand All @@ -40,7 +30,6 @@ linters:
- unparam
- unused
- whitespace
- wsl

issues:
exclude-rules:
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ LDFLAGS := "${ldflags:+$ldflags }-X main.version=${ver}${suff}"
BUILD_FLAGS := -ldflags "-X main.version=$(VERSION_FULL)"
ENV_ROOT := $(shell [ "$$(id -u)" = "0" ] && echo env || echo sudo )

GOLANGCI_VER = v1.52.2
GOLANGCI_VER = v1.56.1
GOLANGCI = ./tools/golangci-lint-$(GOLANGCI_VER)

CMDS := demo/demo ptimg/ptimg
Expand All @@ -18,7 +18,7 @@ all: build check

build: .build $(CMDS)

.build: $(GO_FILES)
.build: $(ALL_GO_FILES)
go build ./...
@touch $@

Expand Down
1 change: 1 addition & 0 deletions demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func main() {
Commands: []*cli.Command{
&diskCommands,
&megaraidCommands,
&smartpqiCommands,
&lvmCommands,
&miscCommands,
},
Expand Down
3 changes: 2 additions & 1 deletion demo/megaraid.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"

"github.com/urfave/cli/v2"
"machinerun.io/disko/linux"
"machinerun.io/disko/megaraid"
)

Expand Down Expand Up @@ -69,7 +70,7 @@ func megaraidDiskSummary(c *cli.Context) error {
}

path := ""
if bname, err := megaraid.NameByDiskID(d.ID); err == nil {
if bname, err := linux.NameByDiskID(mraid.DriverSysfsPath(), d.ID); err == nil {
path = "/dev/" + bname
}

Expand Down
117 changes: 117 additions & 0 deletions demo/smartpqi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package main

import (
"encoding/json"
"fmt"
"strconv"

"github.com/urfave/cli/v2"
"machinerun.io/disko/smartpqi"
)

//nolint:gochecknoglobals
var smartpqiCommands = cli.Command{
Name: "smartpqi",
Usage: "smartpqi / arcconf commands",
Subcommands: []*cli.Command{
{
Name: "dump",
Usage: "Dump information about smartpqi",
Action: smartpqiDump,
},
{
Name: "disk-summary",
Usage: "Show information about virtual devices on system",
Action: smartpqiDiskSummary,
},
{
Name: "list-controllers",
Usage: "Show the discovered controller IDs",
Action: smartpqiListControllers,
},
},
}

func smartpqiListControllers(c *cli.Context) error {
arc := smartpqi.ArcConf()
ctrls, err := arc.List()
if err != nil {
return fmt.Errorf("failed to list controllers: %s", err)
}

fmt.Printf("Found %d controllers.", len(ctrls))
for _, cID := range ctrls {
fmt.Printf("Controller ID: %d\n", cID)
}
return nil
}

func smartpqiDiskSummary(c *cli.Context) error {
var err error
var ctrlNum = 1
var ctrlArg = c.Args().First()

if ctrlArg != "" {
ctrlNum, err = strconv.Atoi(ctrlArg)
if err != nil {
return fmt.Errorf("could not convert to integer: %s", err)
}
}

arc := smartpqi.ArcConf()
ctrl, err := arc.Query(ctrlNum)

if err != nil {
return err
}

data := [][]string{{"Path", "Name", "DiskType", "RAID"}}

for _, ld := range ctrl.LogicalDrives {
stype := "HDD"

if ld.IsSSD() {
stype = "SSD"
}

name := ld.Name
if ld.Name == "" {
name = fmt.Sprintf("logicalid-%d", ld.ID)
}

data = append(data, []string{ld.DiskName, name, stype, ld.RAIDLevel})
}

printTextTable(data)

return nil
}

func smartpqiDump(c *cli.Context) error {
var err error
var ctrlNum = 1
var ctrlArg = c.Args().First()

if ctrlArg != "" {
ctrlNum, err = strconv.Atoi(ctrlArg)
if err != nil {
return fmt.Errorf("could not convert to integer: %s", err)
}
}

arc := smartpqi.ArcConf()
ctrl, err := arc.Query(ctrlNum)

if err != nil {
return err
}

jbytes, err := json.MarshalIndent(&ctrl, "", " ")
if err != nil {
return err
}

fmt.Printf("%s\n", string(jbytes))

return nil
}
8 changes: 4 additions & 4 deletions disk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ func TestDiskString(t *testing.T) {
Type: disko.HDD,
Attachment: disko.ATA,
Partitions: disko.PartitionSet{
1: {Start: 3 * mib, Last: 253*mib - 1, Number: 1},
3: {Start: 500 * mib, Last: 600*mib - 1, Number: 3},
1: disko.Partition{Start: 3 * mib, Last: 253*mib - 1, Number: 1},
3: disko.Partition{Start: 500 * mib, Last: 600*mib - 1, Number: 3},
},
UdevInfo: disko.UdevInfo{},
}
Expand Down Expand Up @@ -93,9 +93,9 @@ func TestDiskDetails(t *testing.T) {
Type: disko.HDD,
Attachment: disko.ATA,
Partitions: disko.PartitionSet{
1: {Start: 3 * mib, Last: 253*mib - 1, Number: 1,
1: disko.Partition{Start: 3 * mib, Last: 253*mib - 1, Number: 1,
Name: "my-name", Type: partid.LinuxLVM},
2: {Start: 253 * mib, Last: 400*mib - 1, Number: 2,
2: disko.Partition{Start: 253 * mib, Last: 400*mib - 1, Number: 2,
Type: disko.PartType(myType)},
},
UdevInfo: disko.UdevInfo{},
Expand Down
17 changes: 17 additions & 0 deletions linux/raidcontroller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package linux

import "machinerun.io/disko"

type RAIDControllerType string

const (
MegaRAIDControllerType RAIDControllerType = "megaraid"
SmartPqiControllerType RAIDControllerType = "smartpqi"
)

type RAIDController interface {
// Type() RAIDControllerType
GetDiskType(string) (disko.DiskType, error)
IsSysPathRAID(string) bool
DriverSysfsPath() string
}
13 changes: 8 additions & 5 deletions linux/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ import (
"machinerun.io/disko/partid"
)

const MiB = 1024 * 1024
const GiB = MiB * 1024
const (
MiB = 1024 * 1024
GiB = MiB * 1024
dtLoopPrefix = "detach loop "
)

// runLog - run command and Printf, useful for debugging errors.
func runLog(args ...string) {
Expand Down Expand Up @@ -112,7 +115,7 @@ func TestRootPartition(t *testing.T) {
runLog("losetup", "-a")
t.Fatalf("failed loop: %s\n", err)
} else {
cl.AddF(cleanup, "detach loop "+tmpFile)
cl.AddF(cleanup, dtLoopPrefix+tmpFile)
loopDev = path
}

Expand Down Expand Up @@ -210,7 +213,7 @@ func TestRootPartitionUpdate(t *testing.T) {
runLog("losetup", "-a")
t.Fatalf("failed loop: %s\n", err)
} else {
cl.AddF(cleanup, "detach loop "+tmpFile)
cl.AddF(cleanup, dtLoopPrefix+tmpFile)
loopDev = path
}

Expand Down Expand Up @@ -297,7 +300,7 @@ func TestRootPartitionDelete(t *testing.T) {
runLog("losetup", "-a")
t.Fatalf("failed loop: %s\n", err)
} else {
cl.AddF(cleanup, "detach loop "+tmpFile)
cl.AddF(cleanup, dtLoopPrefix+tmpFile)
loopDev = path
}

Expand Down
51 changes: 28 additions & 23 deletions linux/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ import (
"golang.org/x/sys/unix"
"machinerun.io/disko"
"machinerun.io/disko/megaraid"
"machinerun.io/disko/smartpqi"
)

type linuxSystem struct {
megaraid megaraid.MegaRaid
raidctrls []RAIDController
}

// System returns an linux specific implementation of disko.System interface.
func System() disko.System {
return &linuxSystem{
megaraid: megaraid.CachingStorCli(),
raidctrls: []RAIDController{
megaraid.CachingStorCli(),
smartpqi.ArcConf(),
},
}
}

Expand Down Expand Up @@ -154,15 +158,22 @@ func (ls *linuxSystem) ScanDisk(devicePath string) (disko.Disk, error) {
return disko.Disk{}, err
}

diskType, err = ls.getDiskType(devicePath, udInfo)
if err != nil {
return disko.Disk{}, err
}

attachType = getAttachType(udInfo)

if megaraid.IsMegaRaidSysPath(udInfo.Properties["DEVPATH"]) {
attachType = disko.RAID
for _, ctrl := range ls.raidctrls {
if IsSysPathRAID(udInfo.Properties["DEVPATH"], ctrl.DriverSysfsPath()) {
// we know this is device is part of a raid, so if we cannot get
// disk type we must return an error
dType, err := ctrl.GetDiskType(devicePath)
if err != nil {
return disko.Disk{}, fmt.Errorf("failed to get diskType of %q from RAID controller: %s", devicePath, err)
}

attachType = disko.RAID
diskType = dType

break
}
}

ro, err = getDiskReadOnly(name)
Expand Down Expand Up @@ -277,22 +288,16 @@ func (ls *linuxSystem) Wipe(d disko.Disk) error {
return udevSettle()
}

func (ls *linuxSystem) getDiskType(path string, udInfo disko.UdevInfo) (disko.DiskType, error) {
ctrl, err := ls.megaraid.Query(0)
if err == nil {
for _, vd := range ctrl.VirtDrives {
if vd.Path == path {
if ctrl.DriveGroups[vd.DriveGroup].IsSSD() {
return disko.SSD, nil
}

return disko.HDD, nil
func (ls *linuxSystem) GetDiskType(path string, udInfo disko.UdevInfo) (disko.DiskType, error) {
for _, ctrl := range ls.raidctrls {
if IsSysPathRAID(udInfo.Properties["DEVPATH"], ctrl.DriverSysfsPath()) {
dType, err := ctrl.GetDiskType(path)
if err != nil {
return disko.HDD, fmt.Errorf("failed to get diskType of %q from RAID controller: %s", path, err)
}

return dType, nil
}
} else if err != megaraid.ErrNoStorcli && err != megaraid.ErrNoController &&
err != megaraid.ErrUnsupported {
return disko.HDD, err
}

return getDiskType(udInfo)
}
Loading

0 comments on commit 7c6624f

Please sign in to comment.