From 750fde5df47b3ba0177d67e342b3810a70a18431 Mon Sep 17 00:00:00 2001 From: akutz Date: Mon, 13 Feb 2017 23:54:55 -0600 Subject: [PATCH] ScaleIO Executor Enhancements This patch enhances the ScaleIO executor so that the `drv_cfg` binary is no longer hard-coded and can now be configured with the configuration property `scaleio.drvCfg` which translates into the environment variable `SCALEIO_DRVCFG`. If the property `scaleio.guid` (env var `SCALEIO_GUID`) is set then the `drv_cfg` binary is not used at all to discover the client's GUID. This patch also updates the logic to discover local devices so the `drv_cfg` is no longer necessary or required to provide this information. --- .../scaleio/executor/scaleio_executor.go | 121 ++++++++---------- drivers/storage/scaleio/scaleio.go | 6 + drivers/storage/scaleio/tests/scaleio_test.go | 11 +- 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/drivers/storage/scaleio/executor/scaleio_executor.go b/drivers/storage/scaleio/executor/scaleio_executor.go index 04b5fd9e..4beb36b8 100644 --- a/drivers/storage/scaleio/executor/scaleio_executor.go +++ b/drivers/storage/scaleio/executor/scaleio_executor.go @@ -3,28 +3,27 @@ package executor import ( - "fmt" "io/ioutil" - "os" "os/exec" + "path" "path/filepath" "regexp" "strings" gofig "github.com/akutz/gofig/types" "github.com/akutz/goof" + "github.com/akutz/gotil" "github.com/codedellemc/libstorage/api/registry" "github.com/codedellemc/libstorage/api/types" "github.com/codedellemc/libstorage/drivers/storage/scaleio" ) -const ( - sioBinPath = "/opt/emc/scaleio/sdc/bin/drv_cfg" -) - // driver is the storage executor for the VFS storage driver. -type driver struct{} +type driver struct { + guid string + drvCfg string +} func init() { registry.RegisterStorageExecutor(scaleio.Name, newdriver) @@ -35,6 +34,9 @@ func newdriver() types.StorageExecutor { } func (d *driver) Init(context types.Context, config gofig.Config) error { + if d.guid = config.GetString("scaleio.guid"); d.guid == "" { + d.drvCfg = config.GetString("scaleio.drvCfg") + } return nil } @@ -49,16 +51,18 @@ func (d *driver) Supported( ctx types.Context, opts types.Store) (bool, error) { - if _, err := os.Stat(sioBinPath); os.IsNotExist(err) { - return false, nil + if d.guid != "" { + return true, nil } - return true, nil + + return gotil.FileExists(d.drvCfg), nil } // NextDevice returns the next available device. func (d *driver) NextDevice( ctx types.Context, opts types.Store) (string, error) { + return "", types.ErrNotImplemented } @@ -78,55 +82,27 @@ func (d *driver) LocalDevices( }, nil } -type sdcMappedVolume struct { - mdmID string - volumeID string - mdmVolumeID string - sdcDevice string -} +const diskIDPath = "/dev/disk/by-id" func getLocalVolumeMap() (map[string]string, error) { - mappedVolumesMap := make(map[string]*sdcMappedVolume) - volumeMap := make(map[string]string) - - out, err := exec.Command(sioBinPath, "--query_vols").Output() + volMap := map[string]string{} + files, err := ioutil.ReadDir(diskIDPath) if err != nil { - return nil, goof.WithError("error querying volumes", err) - } - - result := string(out) - lines := strings.Split(result, "\n") - - for _, line := range lines { - split := strings.Split(line, " ") - if split[0] == "VOL-ID" { - mappedVolume := &sdcMappedVolume{ - mdmID: split[3], - volumeID: split[1], - } - mappedVolume.mdmVolumeID = fmt.Sprintf( - "%s-%s", mappedVolume.mdmID, mappedVolume.volumeID) - mappedVolumesMap[mappedVolume.mdmVolumeID] = mappedVolume - } + return nil, err } - - diskIDPath := "/dev/disk/by-id" - files, _ := ioutil.ReadDir(diskIDPath) - r, _ := regexp.Compile(`^emc-vol-\w*-\w*$`) + diskIDRX := regexp.MustCompile(`(?i)emc-vol-[^-].+-(.+)$`) for _, f := range files { - matched := r.MatchString(f.Name()) - if matched { - mdmVolumeID := strings.Replace(f.Name(), "emc-vol-", "", 1) - devPath, _ := filepath.EvalSymlinks( - fmt.Sprintf("%s/%s", diskIDPath, f.Name())) - if _, ok := mappedVolumesMap[mdmVolumeID]; ok { - volumeID := mappedVolumesMap[mdmVolumeID].volumeID - volumeMap[volumeID] = devPath - } + m := diskIDRX.FindStringSubmatch(f.Name()) + if len(m) == 0 { + continue + } + devPath, err := filepath.EvalSymlinks(path.Join(diskIDPath, f.Name())) + if err != nil { + return nil, err } + volMap[m[1]] = devPath } - - return volumeMap, nil + return volMap, nil } // InstanceID returns the local system's InstanceID. @@ -134,29 +110,40 @@ func (d *driver) InstanceID( ctx types.Context, opts types.Store) (*types.InstanceID, error) { - return GetInstanceID() + return d.getInstanceID() } // GetInstanceID returns the instance ID object -func GetInstanceID() (*types.InstanceID, error) { - sg, err := getSdcLocalGUID() +func GetInstanceID( + ctx types.Context, config gofig.Config) (*types.InstanceID, error) { + + d := &driver{} + d.Init(ctx, config) + return d.getInstanceID() +} + +func (d *driver) getInstanceID() (*types.InstanceID, error) { + + if d.guid != "" { + iid := &types.InstanceID{Driver: scaleio.Name} + if err := iid.MarshalMetadata(d.guid); err != nil { + return nil, err + } + return iid, nil + } + + out, err := exec.Command(d.drvCfg, "--query_guid").CombinedOutput() if err != nil { return nil, err } + if err != nil { + return nil, goof.WithError("error getting sdc guid", err) + } + + sdcGUID := strings.Replace(string(out), "\n", "", -1) iid := &types.InstanceID{Driver: scaleio.Name} - if err := iid.MarshalMetadata(sg); err != nil { + if err := iid.MarshalMetadata(sdcGUID); err != nil { return nil, err } return iid, nil } - -func getSdcLocalGUID() (sdcGUID string, err error) { - out, err := exec.Command(sioBinPath, "--query_guid").Output() - if err != nil { - return "", goof.WithError("problem getting sdc guid", err) - } - - sdcGUID = strings.Replace(string(out), "\n", "", -1) - - return sdcGUID, nil -} diff --git a/drivers/storage/scaleio/scaleio.go b/drivers/storage/scaleio/scaleio.go index 9fe733cf..27131533 100644 --- a/drivers/storage/scaleio/scaleio.go +++ b/drivers/storage/scaleio/scaleio.go @@ -28,6 +28,12 @@ var ( func init() { r := gofigCore.NewRegistration("ScaleIO") + r.Key(gofig.String, "", "", "", "scaleio.guid") + r.Key(gofig.String, + "", + "/opt/emc/scaleio/sdc/bin/drv_cfg", + "", + "scaleio.drvCfg") r.Key(gofig.String, "", "", "", "scaleio.endpoint") r.Key(gofig.Bool, "", false, "", "scaleio.insecure") r.Key(gofig.Bool, "", false, "", "scaleio.useCerts") diff --git a/drivers/storage/scaleio/tests/scaleio_test.go b/drivers/storage/scaleio/tests/scaleio_test.go index e232be6c..27fdc683 100644 --- a/drivers/storage/scaleio/tests/scaleio_test.go +++ b/drivers/storage/scaleio/tests/scaleio_test.go @@ -12,9 +12,11 @@ import ( gofig "github.com/akutz/gofig/types" "github.com/stretchr/testify/assert" + "github.com/codedellemc/libstorage/api/context" "github.com/codedellemc/libstorage/api/server" apitests "github.com/codedellemc/libstorage/api/tests" "github.com/codedellemc/libstorage/api/types" + apiconfig "github.com/codedellemc/libstorage/api/utils/config" // load the driver sio "github.com/codedellemc/libstorage/drivers/storage/scaleio" @@ -63,7 +65,12 @@ func TestInstanceID(t *testing.T) { t.SkipNow() } - iid, err := siox.GetInstanceID() + config, err := apiconfig.NewConfig() + if err != nil { + t.Error(err) + t.FailNow() + } + iid, err := siox.GetInstanceID(context.Background(), config) assert.NoError(t, err) if err != nil { t.Error("failed TestInstanceID") @@ -160,7 +167,7 @@ func TestVolumeCreateRemove(t *testing.T) { func volumeRemove(t *testing.T, client types.Client, volumeID string) { log.WithField("volumeID", volumeID).Info("removing volume") err := client.API().VolumeRemove( - nil, sio.Name, volumeID) + nil, sio.Name, volumeID, false) assert.NoError(t, err) if err != nil { t.Error("failed volumeRemove")