Skip to content

Commit

Permalink
Merge pull request #2 from Seagate/feat/saswork
Browse files Browse the repository at this point in the history
feat: Use klog.Logger, pass by value, connector updates
  • Loading branch information
jskazinski authored Jul 6, 2022
2 parents 8ae2784 + 42a0a01 commit cb93f2d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 23 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ help:
@echo "make clean - remove all generated files"
@echo "make install - install sas"
@echo "make run - build, run example"
@echo "make test - run sas unit test"
@echo ""

all: clean build install
Expand All @@ -25,3 +26,6 @@ install:

run: build
_output/example

test:
go test -v ./sas/
88 changes: 70 additions & 18 deletions sas/sas.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ package sas

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"

"errors"
"path"
"path/filepath"
"strings"

"github.com/go-logr/logr"
"k8s.io/klog/v2"
)

Expand All @@ -39,11 +40,13 @@ type ioHandler interface {

//Connector provides a struct to hold all of the needed parameters to make our SAS connection
type Connector struct {
VolumeName string
TargetWWNs []string
Lun string
WWIDs []string
io ioHandler
VolumeName string `json:"volume_name"`
TargetWWNs []string `json:"target_wwns"`
Lun string `json:"lun"`
WWIDs []string `json:"wwids"`
Multipath bool `json:"multipath"`
DevicePath string `json:"device_path"`
IoHandler ioHandler
}

//OSioHandler is a wrapper that includes all the necessary io functions used for (Should be used as default io handler)
Expand All @@ -60,13 +63,15 @@ func Attach(ctx context.Context, c Connector, io ioHandler) (string, error) {
}

logger.V(1).Info("Attaching SAS volume")
devicePath, err := searchDisk(&logger, c, io)
devicePath, err := searchDisk(logger, c, io)

if err != nil {
logger.V(1).Info("unable to find disk given WWNN or WWIDs")
return "", err
}

c.DevicePath = devicePath

return devicePath, nil
}

Expand Down Expand Up @@ -98,10 +103,10 @@ func Detach(ctx context.Context, devicePath string, io ioHandler) error {
var lastErr error

for _, device := range devices {
err := detachFCDisk(&logger, device, io)
err := detachSasDisk(logger, device, io)
if err != nil {
logger.Error(err, "sas: detachFCDisk failed", "device", device)
lastErr = fmt.Errorf("sas: detachFCDisk failed. device: %v err: %v", device, err)
logger.Error(err, "sas: detachSasDisk failed", "device", device)
lastErr = fmt.Errorf("sas: detachSasDisk failed. device: %v err: %v", device, err)
}
}

Expand All @@ -113,6 +118,50 @@ func Detach(ctx context.Context, devicePath string, io ioHandler) error {
return nil
}

// Persist persists the Connector to the specified file (ie /var/lib/pfile/myConnector.json)
func (c *Connector) Persist(ctx context.Context, filePath string) error {
logger := klog.FromContext(ctx)
f, err := os.Create(filePath)
if err != nil {
logger.Error(err, "Could not create file", "filePath", filePath)
return fmt.Errorf("error creating iSCSI persistence file %s: %s", filePath, err)
}
defer f.Close()
encoder := json.NewEncoder(f)
if err = encoder.Encode(c); err != nil {
logger.Error(err, "Could not encode the connector")
return fmt.Errorf("error encoding connector: %v", err)
}
return nil
}

// GetConnectorFromFile attempts to create a Connector using the specified json file (ie /var/lib/pfile/myConnector.json)
func GetConnectorFromFile(filePath string) (*Connector, error) {
f, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}
c := Connector{}
err = json.Unmarshal([]byte(f), &c)
if err != nil {
return nil, err
}

return &c, nil
}

// ResizeMultipathDevice: resize a multipath device based on its underlying devices
func ResizeMultipathDevice(ctx context.Context, devicePath string) error {
logger := klog.FromContext(ctx)
logger.V(1).Info("Resizing multipath device", "device", devicePath)

if output, err := exec.Command("multipathd", "resize", "map", devicePath).CombinedOutput(); err != nil {
return fmt.Errorf("could not resize multipath device: %s (%v)", output, err)
}

return nil
}

// PRIVATE

//ReadDir calls the ReadDir function from ioutil package
Expand Down Expand Up @@ -174,7 +223,7 @@ func findDeviceForPath(path string, io ioHandler) (string, error) {
return "", errors.New("Illegal path for device " + devicePath)
}

func scsiHostRescan(logger *logr.Logger, io ioHandler) {
func scsiHostRescan(logger klog.Logger, io ioHandler) {
scsiPath := "/sys/class/scsi_host/"
logger.V(4).Info("scsi host rescan", "scsiPath", scsiPath)
if dirs, err := io.ReadDir(scsiPath); err == nil {
Expand All @@ -187,7 +236,7 @@ func scsiHostRescan(logger *logr.Logger, io ioHandler) {
}
}

func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error) {
func searchDisk(logger klog.Logger, c Connector, io ioHandler) (string, error) {
var diskIds []string
var disk string
var dm string
Expand All @@ -198,7 +247,10 @@ func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error)
diskIds = c.WWIDs
}

c.Multipath = false

rescaned := false

// two-phase search:
// first phase, search existing device path, if a multipath dm is found, exit loop
// otherwise, in second phase, rescan scsi bus and search again, return with any findings
Expand Down Expand Up @@ -234,6 +286,7 @@ func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error)

// if multipath devicemapper device is found, use it; otherwise use raw disk
if dm != "" {
c.Multipath = true
logger.V(1).Info("multipath device was discovered", "dm", dm)
return dm, nil
}
Expand All @@ -242,8 +295,7 @@ func searchDisk(logger *logr.Logger, c Connector, io ioHandler) (string, error)
}

// given a wwn and lun, find the device and associated devicemapper parent
func findDisk(logger *logr.Logger, wwn, lun string, io ioHandler) (string, string) {
// FcPath := "-fc-0x" + wwn + "-lun-" + lun
func findDisk(logger klog.Logger, wwn, lun string, io ioHandler) (string, string) {
logger.V(4).Info("find disk", "wwn", wwn, "lun", lun)
wwnPath := "wwn-0x" + wwn
DevPath := "/dev/disk/by-id/"
Expand All @@ -267,7 +319,7 @@ func findDisk(logger *logr.Logger, wwn, lun string, io ioHandler) (string, strin
}

// given a wwid, find the device and associated devicemapper parent
func findDiskWWIDs(logger *logr.Logger, wwid string, io ioHandler) (string, string) {
func findDiskWWIDs(logger klog.Logger, wwid string, io ioHandler) (string, string) {
// Example wwid format:
// 3600508b400105e210000900000490000
// <VENDOR NAME> <IDENTIFIER NUMBER>
Expand Down Expand Up @@ -319,8 +371,8 @@ func FindSlaveDevicesOnMultipath(dm string, io ioHandler) []string {
return devices
}

// detachFCDisk removes scsi device file such as /dev/sdX from the node.
func detachFCDisk(logger *logr.Logger, devicePath string, io ioHandler) error {
// detachSasDisk removes scsi device file such as /dev/sdX from the node.
func detachSasDisk(logger klog.Logger, devicePath string, io ioHandler) error {
// Remove scsi device from the node.
if !strings.HasPrefix(devicePath, "/dev/") {
return fmt.Errorf("sas detach disk: invalid device name: %s", devicePath)
Expand All @@ -332,7 +384,7 @@ func detachFCDisk(logger *logr.Logger, devicePath string, io ioHandler) error {
}

// Removes a scsi device based upon /dev/sdX name
func removeFromScsiSubsystem(logger *logr.Logger, deviceName string, io ioHandler) {
func removeFromScsiSubsystem(logger klog.Logger, deviceName string, io ioHandler) {
fileName := "/sys/block/" + deviceName + "/device/delete"
logger.Info("sas: remove device from scsi-subsystem", "path", fileName)
data := []byte("1")
Expand Down
15 changes: 10 additions & 5 deletions sas/sas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"os"
"testing"
"time"

"k8s.io/klog/v2/ktesting"
)

type fakeFileInfo struct {
Expand Down Expand Up @@ -64,7 +66,7 @@ func (handler *fakeIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
return []os.FileInfo{f}, nil
case "/dev/disk/by-id/":
f := &fakeFileInfo{
name: "scsi-3600508b400105e210000900000490000",
name: "wwn-0x500a0981891b8dc5",
}
return []os.FileInfo{f}, nil
}
Expand All @@ -84,31 +86,34 @@ func (handler *fakeIOHandler) WriteFile(filename string, data []byte, perm os.Fi
}

func TestSearchDisk(t *testing.T) {
logger, _ := ktesting.NewTestContext(t)
fakeConnector := Connector{
VolumeName: "fakeVol",
TargetWWNs: []string{"500a0981891b8dc5"},
Lun: "0",
}

devicePath, error := searchDisk(fakeConnector, &fakeIOHandler{})
devicePath, error := searchDisk(logger, fakeConnector, &fakeIOHandler{})

if devicePath == "" || error != nil {
t.Errorf("no fc disk found")
t.Errorf("no disk found")
}
}

func TestInvalidWWN(t *testing.T) {
logger, _ := ktesting.NewTestContext(t)
testWwn := "INVALIDWWN"
disk, dm := findDisk(testWwn, "1", &fakeIOHandler{})
disk, dm := findDisk(logger, testWwn, "1", &fakeIOHandler{})

if disk != "" && dm != "" {
t.Error("Found a disk with WWN that does not Exist")
}
}

func TestInvalidWWID(t *testing.T) {
logger, _ := ktesting.NewTestContext(t)
testWWID := "INVALIDWWID"
disk, dm := findDiskWWIDs(testWWID, &fakeIOHandler{})
disk, dm := findDiskWWIDs(logger, testWWID, &fakeIOHandler{})

if disk != "" && dm != "" {
t.Error("Found a disk with WWID that does not Exist")
Expand Down

0 comments on commit cb93f2d

Please sign in to comment.