mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix: fail to detect lv by megacli64 and storecli (#19880)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user