Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for smartpqi #130

Merged
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
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
hallyn marked this conversation as resolved.
Show resolved Hide resolved
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 @@
"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 @@
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)

Check warning on line 169 in linux/system.go

View check run for this annotation

Codecov / codecov/patch

linux/system.go#L167-L169

Added lines #L167 - L169 were not covered by tests
}

attachType = disko.RAID
diskType = dType

Check warning on line 173 in linux/system.go

View check run for this annotation

Codecov / codecov/patch

linux/system.go#L172-L173

Added lines #L172 - L173 were not covered by tests

break

Check warning on line 175 in linux/system.go

View check run for this annotation

Codecov / codecov/patch

linux/system.go#L175

Added line #L175 was not covered by tests
}
}

ro, err = getDiskReadOnly(name)
Expand Down Expand Up @@ -277,22 +288,16 @@
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)

Check warning on line 296 in linux/system.go

View check run for this annotation

Codecov / codecov/patch

linux/system.go#L291-L296

Added lines #L291 - L296 were not covered by tests
}

return dType, nil

Check warning on line 299 in linux/system.go

View check run for this annotation

Codecov / codecov/patch

linux/system.go#L299

Added line #L299 was not covered by tests
}
} else if err != megaraid.ErrNoStorcli && err != megaraid.ErrNoController &&
err != megaraid.ErrUnsupported {
return disko.HDD, err
}

return getDiskType(udInfo)
}
Loading
Loading