ScaleIO - Specify SDC GUID value via node label

The commit allow ScaleIO volume plugin to read SDC GUID value as a node label.
If binary drv_cfg is not installed, the plugin will still work properly.
If node label not found, it defaults to drv_cfg if installed.
This commit is contained in:
Vladimir Vivien 2017-08-09 14:55:29 -04:00
parent 424819888a
commit 314859538e
5 changed files with 92 additions and 28 deletions

View File

@ -74,6 +74,7 @@ type sioClient struct {
spClient *sio.StoragePool
provisionMode string
sdcPath string
sdcGuid string
instanceID string
inited bool
diskRegex *regexp.Regexp
@ -292,28 +293,43 @@ func (c *sioClient) DeleteVolume(id sioVolumeID) error {
return nil
}
// IID returns the scaleio instance id for node
func (c *sioClient) IID() (string, error) {
if err := c.init(); err != nil {
return "", err
}
// if instanceID not set, retrieve it
if c.instanceID == "" {
guid, err := c.getGuid()
if err != nil {
return "", err
}
sdc, err := c.sysClient.FindSdc("SdcGuid", guid)
if err != nil {
glog.Error(log("failed to retrieve sdc info %s", err))
return "", err
}
c.instanceID = sdc.Sdc.ID
glog.V(4).Info(log("retrieved instanceID %s", c.instanceID))
}
return c.instanceID, nil
}
// getGuid returns instance GUID, if not set using resource labels
// it attemps to fallback to using drv_cfg binary
func (c *sioClient) getGuid() (string, error) {
if c.sdcGuid == "" {
glog.V(4).Info(log("sdc guid label not set, falling back to using drv_cfg"))
cmd := c.getSdcCmd()
output, err := c.exec.Run(cmd, "--query_guid")
if err != nil {
glog.Error(log("drv_cfg --query_guid failed: %v", err))
return "", err
}
guid := strings.TrimSpace(string(output))
sdc, err := c.sysClient.FindSdc("SdcGuid", guid)
if err != nil {
glog.Error(log("failed to get sdc info %s", err))
return "", err
}
c.instanceID = sdc.Sdc.ID
glog.V(4).Info(log("got instanceID %s", c.instanceID))
c.sdcGuid = strings.TrimSpace(string(output))
}
return c.instanceID, nil
return c.sdcGuid, nil
}
// getSioDiskPaths traverse local disk devices to retrieve device path

View File

@ -81,6 +81,7 @@ func (m *sioMgr) getClient() (sioInterface, error) {
client.spName = configs[confKey.storagePool]
client.sdcPath = configs[confKey.sdcRootPath]
client.provisionMode = configs[confKey.storageMode]
client.sdcGuid = configs[confKey.sdcGuid]
m.client = client
@ -215,23 +216,12 @@ func (m *sioMgr) DeleteVolume(volName string) error {
if err != nil {
return err
}
iid, err := client.IID()
if err != nil {
glog.Error(log("failed to get instanceID: %v", err))
return err
}
vol, err := client.FindVolume(volName)
if err != nil {
return err
}
// if still attached, stop
if m.isSdcMappedToVol(iid, vol) {
glog.Error(log("volume %s still attached, unable to delete", volName))
return errors.New("volume still attached")
}
if err := client.DeleteVolume(sioVolumeID(vol.ID)); err != nil {
glog.Error(log("failed to delete volume %s: %v", volName, err))
return err
@ -242,10 +232,6 @@ func (m *sioMgr) DeleteVolume(volName string) error {
}
//*****************************************************************
// Helpers
//*****************************************************************
// isSdcMappedToVol returns true if the sdc is mapped to the volume
func (m *sioMgr) isSdcMappedToVol(sdcID string, vol *siotypes.Volume) bool {
if len(vol.MappedSdcInfo) == 0 {

View File

@ -47,7 +47,8 @@ var (
readOnly,
username,
password,
namespace string
namespace,
sdcGuid string
}{
gateway: "gateway",
sslEnabled: "sslEnabled",
@ -64,9 +65,10 @@ var (
username: "username",
password: "password",
namespace: "namespace",
sdcGuid: "sdcGuid",
}
nsSep = "%"
sdcRootPath = "/opt/emc/scaleio/sdc/bin"
sdcGuidLabelName = "scaleio.sdcGuid"
sdcRootPath = "/opt/emc/scaleio/sdc/bin"
secretNotFoundErr = errors.New("secret not found")
configMapNotFoundErr = errors.New("configMap not found")
@ -215,6 +217,33 @@ func attachSecret(plug *sioPlugin, namespace string, configData map[string]strin
return nil
}
// attachSdcGuid injects the sdc guid node label value into config
func attachSdcGuid(plug *sioPlugin, conf map[string]string) error {
guid, err := getSdcGuidLabel(plug)
if err != nil {
return err
}
conf[confKey.sdcGuid] = guid
return nil
}
// getSdcGuidLabel fetches the scaleio.sdcGuid node label
// associated with the node executing this code.
func getSdcGuidLabel(plug *sioPlugin) (string, error) {
nodeLabels, err := plug.host.GetNodeLabels()
if err != nil {
return "", err
}
label, ok := nodeLabels[sdcGuidLabelName]
if !ok {
glog.V(4).Info(log("node label %s not found", sdcGuidLabelName))
return "", nil
}
glog.V(4).Info(log("found node label %s=%s", sdcGuidLabelName, label))
return label, nil
}
// getVolumeSourceFromSpec safely extracts ScaleIOVolumeSource from spec
func getVolumeSourceFromSpec(spec *volume.Spec) (*api.ScaleIOVolumeSource, error) {
if spec.Volume != nil && spec.Volume.ScaleIO != nil {

View File

@ -386,7 +386,13 @@ func (v *sioVolume) setSioMgr() error {
return err
}
// merge in Sdc Guid label value
if err := attachSdcGuid(v.plugin, configData); err != nil {
glog.Error(log("failed to retrieve sdc guid: %v", err))
return err
}
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil {
glog.Error(log("failed to reset sio manager: %v", err))
return err
@ -418,7 +424,14 @@ func (v *sioVolume) resetSioMgr() error {
return err
}
// merge in Sdc Guid label value
if err := attachSdcGuid(v.plugin, configData); err != nil {
glog.Error(log("failed to retrieve sdc guid: %v", err))
return err
}
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil {
glog.Error(log("failed to reset scaleio mgr: %v", err))
return err
@ -453,6 +466,7 @@ func (v *sioVolume) setSioMgrFromConfig() error {
}
mgr, err := newSioMgr(data, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil {
glog.Error(log("failed while setting scaleio mgr from config: %v", err))
return err
@ -462,6 +476,8 @@ func (v *sioVolume) setSioMgrFromConfig() error {
return nil
}
// setSioMgrFromSpec sets the scaleio manager from a spec object.
// The spec may be complete or incomplete depending on lifecycle phase.
func (v *sioVolume) setSioMgrFromSpec() error {
glog.V(4).Info(log("setting sio manager from spec"))
if v.sioMgr == nil {
@ -482,6 +498,7 @@ func (v *sioVolume) setSioMgrFromSpec() error {
}
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
if err != nil {
glog.Error(log("failed to reset sio manager: %v", err))
return err

View File

@ -60,8 +60,14 @@ func newPluginMgr(t *testing.T) (*volume.VolumePluginMgr, string) {
"password": []byte("password"),
},
}
fakeClient := fakeclient.NewSimpleClientset(config)
host := volumetest.NewFakeVolumeHost(tmpDir, fakeClient, nil)
host := volumetest.NewFakeVolumeHostWithNodeLabels(
tmpDir,
fakeClient,
nil,
map[string]string{sdcGuidLabelName: "abc-123"},
)
plugMgr := &volume.VolumePluginMgr{}
plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
@ -195,6 +201,11 @@ func TestVolumeMounterUnmounter(t *testing.T) {
t.Errorf("SetUp() - expecting multiple volume disabled by default")
}
// did we read sdcGuid label
if _, ok := sioVol.sioMgr.configData[confKey.sdcGuid]; !ok {
t.Errorf("Expected to find node label scaleio.sdcGuid, but did not find it")
}
// rebuild spec
builtSpec, err := sioPlug.ConstructVolumeSpec(volume.NewSpecFromVolume(vol).Name(), path)
if err != nil {
@ -322,6 +333,11 @@ func TestVolumeProvisioner(t *testing.T) {
t.Fatalf("Expected success, got: %v", err)
}
// did we read sdcGuid label
if _, ok := sioVol.sioMgr.configData[confKey.sdcGuid]; !ok {
t.Errorf("Expected to find node label scaleio.sdcGuid, but did not find it")
}
// isMultiMap applied
if !sio.isMultiMap {
t.Errorf("SetUp() expecting attached volume with multi-mapping")