fix: fail to detect lv by megacli64 and storecli (#19880)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2024-04-08 00:26:55 +08:00
committed by GitHub
co-authored by Qiu Jian
parent f935d2a62d
commit a764ddedfa
4 changed files with 142 additions and 91 deletions
+53 -36
View File
@@ -444,16 +444,25 @@ func (adapter *MegaRaidAdaptor) GetDevices() []*baremetal.BaremetalStorage {
}
func (adapter *MegaRaidAdaptor) GetLogicVolumes() ([]*raiddrivers.RaidLogicalVolume, error) {
lvs, err := adapter.getMegacliLogicVolumes()
if err == nil {
return lvs, nil
}
errs := []error{err}
if lvs, err := adapter.getStorcliLogicVolums(); err == nil {
return lvs, nil
} else {
errs := make([]error, 0)
megaLvs, err := adapter.getMegacliLogicVolumes()
if err != nil {
errs = append(errs, err)
}
storeLvs, err := adapter.getStorcliLogicVolums()
if err != nil {
errs = append(errs, err)
}
if len(megaLvs) > 0 {
return megaLvs, nil
}
if len(storeLvs) > 0 {
return storeLvs, nil
}
if len(errs) == 0 {
// no error, no volume
return []*raiddrivers.RaidLogicalVolume{}, nil
}
return nil, errors.NewAggregate(errs)
}
@@ -461,24 +470,18 @@ func (adapter *MegaRaidAdaptor) getMegacliLogicVolumes() ([]*raiddrivers.RaidLog
cmd := GetCommand("-LDInfo", "-Lall", fmt.Sprintf("-a%d", adapter.index))
ret, err := adapter.remoteRun(cmd)
if err != nil {
return nil, fmt.Errorf("getMegacliLogicVolumes error: %v", err)
return nil, errors.Wrapf(err, "remoteRun %s", cmd)
}
return adapter.parseLogicVolumes(ret)
lvs, err := adapter.parseLogicVolumes(ret)
if err != nil {
return nil, errors.Wrap(err, "")
}
for i := range lvs {
lvs[i].Driver = raiddrivers.RaidDriverToolMegacli64
}
return lvs, nil
}
// func (adapter *MegaRaidAdaptor) getStorcliLogicVolums() ([]*raiddrivers.RaidLogicalVolume, error) {
// cmd := GetCommand2(fmt.Sprintf("/c%d/vall", adapter.index), "show")
// ret, err := adapter.remoteRun(cmd)
// if err != nil {
// return nil, fmt.Errorf("getStorcliLogicVolums error: %v", err)
// }
// lvs, err := parseStorcliLogicalVolumes(adapter.index, ret)
// if err != nil {
// return nil, err
// }
// return lvs, nil
// }
func (adapter *MegaRaidAdaptor) getStorcliLogicVolums() ([]*raiddrivers.RaidLogicalVolume, error) {
lvs, err := adapter.getStorcliLogicVolumsV2()
if err != nil {
@@ -488,10 +491,11 @@ func (adapter *MegaRaidAdaptor) getStorcliLogicVolums() ([]*raiddrivers.RaidLogi
for i := range lvs {
lv := lvs[i]
ret[i] = &raiddrivers.RaidLogicalVolume{
Index: i,
Index: lv.Index,
Adapter: adapter.index,
BlockDev: lv.GetOSDevice(),
IsSSD: tristate.NewFromBool(lv.IsSSD()),
Driver: raiddrivers.RaidDriverToolStorecli,
}
}
return ret, nil
@@ -905,21 +909,34 @@ func (adapter *MegaRaidAdaptor) megacliBuildJBOD(devs []*baremetal.BaremetalStor
func (adapter *MegaRaidAdaptor) RemoveLogicVolumes() error {
lvIdx, err := adapter.GetLogicVolumes()
if err != nil {
return err
return errors.Wrap(err, "GetLogicVolumes")
}
for _, i := range raiddrivers.ReverseLogicalArray(lvIdx) {
cmd := GetCommand("-CfgLdDel", fmt.Sprintf("-L%d", i.Index), "-Force", fmt.Sprintf("-a%d", adapter.index))
_, err := adapter.remoteRun(cmd)
if err == nil {
continue
}
errs := []error{err}
cmd = GetCommand2(fmt.Sprintf("/c%d/v%d", adapter.index, i.Index), "delete", "force")
if _, err := adapter.remoteRun(cmd); err != nil {
errs = append(errs, err)
return errors.NewAggregate(errs)
if len(lvIdx) == 0 {
log.Infof("RemoveLogicVolumes: no logical volume to delete!")
return nil
}
errs := make([]error, 0)
lvIdx = raiddrivers.ReverseLogicalArray(lvIdx)
for i := range lvIdx {
lv := lvIdx[i]
switch lv.Driver {
case raiddrivers.RaidDriverToolMegacli64:
cmd := GetCommand("-CfgLdDel", fmt.Sprintf("-L%d", lv.Index), "-Force", fmt.Sprintf("-a%d", adapter.index))
_, err := adapter.remoteRun(cmd)
if err != nil {
errs = append(errs, err)
}
case raiddrivers.RaidDriverToolStorecli:
cmd := GetCommand2(fmt.Sprintf("/c%d/v%d", adapter.index, lv.Index), "delete", "force")
_, err := adapter.remoteRun(cmd)
if err != nil {
errs = append(errs, err)
}
}
}
if len(errs) > 0 {
return errors.NewAggregate(errs)
}
return nil
}
+66 -47
View File
@@ -22,6 +22,7 @@ import (
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
@@ -279,6 +280,50 @@ type StorcliLogicalVolume struct {
Index int
}
func fetchLvInfo(data *jsonutils.JSONDict, keyIdx string, vIdx int) (*StorcliLogicalVolume, error) {
lvObj, err := data.Get(keyIdx)
if err != nil {
return nil, errors.Wrapf(err, "Get %s", keyIdx)
}
// parse PDs
pdKey := fmt.Sprintf("PDs for VD %d", vIdx)
if !data.Contains(pdKey) {
return nil, nil
}
lvArr := make([]*StorcliLogicalVolume, 0)
if err := lvObj.Unmarshal(&lvArr); err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s to StorcliLogicalVolume", lvObj)
}
lv := lvArr[0]
lv.Index = vIdx
lv.Name = keyIdx
pdObj, err := data.Get(pdKey)
if err != nil {
return nil, errors.Wrapf(err, "Get %s", pdKey)
}
pds := make([]*StorcliLogicalVolumePD, 0)
if err := pdObj.Unmarshal(&pds); err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s to PDs", pdObj)
}
lv.PDs = pds
// parse Properties
ppKey := fmt.Sprintf("VD%d Properties", vIdx)
ppObj, err := data.Get(ppKey)
if err != nil {
return nil, errors.Wrapf(err, "Get %s", ppKey)
}
props := new(StorcliLogicalVolumeProperties)
if err := ppObj.Unmarshal(props); err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s to Properties", ppObj)
}
lv.Properties = props
return lv, nil
}
func (lvs *StorcliLogicalVolumes) GetLogicalVolumes(controller int) ([]*StorcliLogicalVolume, error) {
data, err := lvs.responseData(controller)
if err != nil {
@@ -287,55 +332,29 @@ func (lvs *StorcliLogicalVolumes) GetLogicalVolumes(controller int) ([]*StorcliL
}
return nil, errors.Wrap(err, "responseData")
}
vIdx := 0
result := make([]*StorcliLogicalVolume, 0)
for {
// find volumes of controller
keyIdx := fmt.Sprintf("/c%d/v%d", controller, vIdx)
if !data.Contains(keyIdx) {
break
dataMap, err := data.GetMap()
if err != nil {
return nil, errors.Wrap(err, "response data get map")
}
vdPrefix := fmt.Sprintf("/c%d/v", controller)
for k := range dataMap {
if strings.HasPrefix(k, vdPrefix) {
// find a LV like cXvXXX
vIdx, err := strconv.ParseInt(k[len(vdPrefix):], 10, 64)
if err != nil {
log.Errorf("key %s not a valid LV key: %s", k, err)
continue
}
lv, err := fetchLvInfo(data, k, int(vIdx))
if err != nil {
log.Errorf("fetchLvInfo %s failed %s", k, err)
continue
}
if lv != nil {
result = append(result, lv)
}
}
lvObj, err := data.Get(keyIdx)
if err != nil {
return nil, errors.Wrapf(err, "Get %s", keyIdx)
}
// parse PDs
pdKey := fmt.Sprintf("PDs for VD %d", vIdx)
if !data.Contains(pdKey) {
break
}
lvArr := make([]*StorcliLogicalVolume, 0)
if err := lvObj.Unmarshal(&lvArr); err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s to StorcliLogicalVolume", lvObj)
}
lv := lvArr[0]
lv.Index = vIdx
lv.Name = keyIdx
pdObj, err := data.Get(pdKey)
if err != nil {
return nil, errors.Wrapf(err, "Get %s", pdKey)
}
pds := make([]*StorcliLogicalVolumePD, 0)
if err := pdObj.Unmarshal(&pds); err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s to PDs", pdObj)
}
lv.PDs = pds
// parse Properties
ppKey := fmt.Sprintf("VD%d Properties", vIdx)
ppObj, err := data.Get(ppKey)
if err != nil {
return nil, errors.Wrapf(err, "Get %s", ppKey)
}
props := new(StorcliLogicalVolumeProperties)
if err := ppObj.Unmarshal(props); err != nil {
return nil, errors.Wrapf(err, "Unmarshal %s to Properties", ppObj)
}
lv.Properties = props
result = append(result, lv)
vIdx++
}
return result, nil
}
@@ -656,12 +656,18 @@ func TestStorcliLogicalVolumes_GetLogicalVolumes(t *testing.T) {
assert := assert.New(t)
assert.Equal(7, len(lvs), "Should 7 logical volumes")
first2SDDs := lvs[0].PDs
assert.Equal("SSD", first2SDDs[0].Med)
assert.Equal("446.625 GB", first2SDDs[0].Size)
assert.Equal("SSD", first2SDDs[1].Med)
assert.Equal("446.625 GB", first2SDDs[1].Size)
assert.Equal(true, lvs[0].IsSSD())
assert.Equal("/dev/sda", lvs[0].Properties.DeviceName)
assert.Equal("/dev/sdg", lvs[6].Properties.DeviceName)
for i := range lvs {
switch lvs[i].Index {
case 0:
first2SDDs := lvs[i].PDs
assert.Equal("SSD", first2SDDs[0].Med)
assert.Equal("446.625 GB", first2SDDs[0].Size)
assert.Equal("SSD", first2SDDs[1].Med)
assert.Equal("446.625 GB", first2SDDs[1].Size)
assert.Equal(true, lvs[i].IsSSD())
assert.Equal("/dev/sda", lvs[i].Properties.DeviceName)
case 6:
assert.Equal("/dev/sdg", lvs[i].Properties.DeviceName)
}
}
}
+9
View File
@@ -137,11 +137,20 @@ func ReverseLogicalArray(input []*RaidLogicalVolume) []*RaidLogicalVolume {
return s
}
type TRaidDriverToolType string
const (
RaidDriverToolMegacli64 = TRaidDriverToolType("megacli64")
RaidDriverToolStorecli = TRaidDriverToolType("storecli")
)
type RaidLogicalVolume struct {
Index int
Adapter int
BlockDev string
IsSSD tristate.TriState
Driver TRaidDriverToolType
}
func SGMap(term IExecTerm) ([]compute.SGMapItem, error) {