fix(baremetal): storcli set sysblock rotational of SSD logical volume (#14424)

This commit is contained in:
Zexi Li
2022-06-10 18:22:12 +08:00
committed by GitHub
parent b5a95f25f4
commit aa51950271
21 changed files with 1260 additions and 471 deletions
+93 -52
View File
@@ -2516,10 +2516,10 @@ func (s *SBaremetalServer) GetDiskConfig() ([]*api.BaremetalDiskConfig, error) {
return baremetal.GetLayoutRaidConfig(layouts), nil
}
func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) error {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, true)
func (s *SBaremetalServer) NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
if err != nil {
return err
return nil, errors.Wrap(err, "DetectStorageInfo")
}
storages := make([]*baremetal.BaremetalStorage, 0)
storages = append(storages, raid...)
@@ -2527,11 +2527,52 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) error {
storages = append(storages, pcie...)
confs, err := s.GetDiskConfig()
if err != nil {
return err
return nil, err
}
layouts, err := baremetal.CalculateLayout(confs, storages)
if err != nil {
return fmt.Errorf("CalculateLayout: %v", err)
return nil, fmt.Errorf("CalculateLayout: %v", err)
}
diskConfs := baremetal.GroupLayoutResultsByDriverAdapter(layouts)
for _, dConf := range diskConfs {
driver := dConf.Driver
adapter := dConf.Adapter
raidDrv := raiddrivers.GetDriver(driver, term)
if raidDrv != nil {
if err := raidDrv.ParsePhyDevs(); err != nil {
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
}
if err := raiddrivers.PostBuildRaid(raidDrv, adapter); err != nil {
return nil, fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
}
time.Sleep(10 * time.Second) // wait 10 seconds for raid status OK
}
}
tool, err := disktool.NewSSHPartitionTool(term, layouts)
if err != nil {
return nil, errors.Wrap(err, "NewSSHPartitionTool")
}
return tool, nil
}
func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitionTool, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, true)
if err != nil {
return nil, errors.Wrap(err, "DetectStorageInfo")
}
storages := make([]*baremetal.BaremetalStorage, 0)
storages = append(storages, raid...)
storages = append(storages, nonRaid...)
storages = append(storages, pcie...)
confs, err := s.GetDiskConfig()
if err != nil {
return nil, err
}
layouts, err := baremetal.CalculateLayout(confs, storages)
if err != nil {
return nil, fmt.Errorf("CalculateLayout: %v", err)
}
log.Errorf("===layouts: %s", jsonutils.Marshal(layouts).PrettyString())
diskConfs := baremetal.GroupLayoutResultsByDriverAdapter(layouts)
@@ -2541,7 +2582,7 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) error {
raidDrv := raiddrivers.GetDriver(driver, term)
if raidDrv != nil {
if err := raidDrv.ParsePhyDevs(); err != nil {
return fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
}
raidDrv.CleanRaid()
}
@@ -2553,10 +2594,10 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) error {
raidDrv := raiddrivers.GetDriver(driver, term)
if raidDrv != nil {
if err := raidDrv.ParsePhyDevs(); err != nil {
return fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
return nil, fmt.Errorf("RaidDriver %s parse physical devices: %v", raidDrv.GetName(), err)
}
if err := raiddrivers.BuildRaid(raidDrv, dConf.Configs, adapter); err != nil {
return fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
return nil, fmt.Errorf("Build %s raid failed: %v", raidDrv.GetName(), err)
}
time.Sleep(10 * time.Second) // wait 10 seconds for raid status OK
}
@@ -2564,7 +2605,7 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) error {
tool, err := disktool.NewSSHPartitionTool(term, layouts)
if err != nil {
return err
return nil, errors.Wrap(err, "NewSSHPartitionTool")
}
maxTries := 60
for tried := 0; !tool.IsAllDisksReady() && tried < maxTries; tried++ {
@@ -2574,10 +2615,10 @@ func (s *SBaremetalServer) DoDiskConfig(term *ssh.Client) error {
}
if !tool.IsAllDisksReady() {
return fmt.Errorf("Raid disks are not ready???")
return nil, fmt.Errorf("Raid disks are not ready???")
}
return nil
return tool, nil
}
func (s *SBaremetalServer) DoDiskUnconfig(term *ssh.Client) error {
@@ -2623,7 +2664,7 @@ func (s *SBaremetalServer) doCreateRoot(term *ssh.Client, devName string) error
return nil
}
func (s *SBaremetalServer) DoPartitionDisk(term *ssh.Client) ([]*disktool.Partition, error) {
func (s *SBaremetalServer) DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
if err != nil {
return nil, err
@@ -2632,19 +2673,19 @@ func (s *SBaremetalServer) DoPartitionDisk(term *ssh.Client) ([]*disktool.Partit
storages = append(storages, raid...)
storages = append(storages, nonRaid...)
storages = append(storages, pcie...)
confs, err := s.GetDiskConfig()
if err != nil {
return nil, errors.Wrapf(err, "do disk config")
}
layouts, err := baremetal.CalculateLayout(confs, storages)
if err != nil {
return nil, errors.Wrapf(err, "CalculateLayout")
}
tool, err := disktool.NewSSHPartitionTool(term, layouts)
if err != nil {
return nil, errors.Wrapf(err, "NewSSHPartitionTool")
}
// confs, err := s.GetDiskConfig()
// if err != nil {
// return nil, errors.Wrapf(err, "do disk config")
// }
// layouts, err := baremetal.CalculateLayout(confs, storages)
// if err != nil {
// return nil, errors.Wrapf(err, "CalculateLayout")
// }
//
// tool, err := disktool.NewSSHPartitionTool(term, layouts)
// if err != nil {
// return nil, errors.Wrapf(err, "NewSSHPartitionTool")
// }
disks, _ := s.desc.GetArray("disks")
if len(disks) == 0 {
@@ -2698,28 +2739,28 @@ func (s *SBaremetalServer) DoPartitionDisk(term *ssh.Client) ([]*disktool.Partit
return tool.GetPartitions(), nil
}
func (s *SBaremetalServer) DoRebuildRootDisk(term *ssh.Client) ([]*disktool.Partition, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
if err != nil {
return nil, err
}
storages := make([]*baremetal.BaremetalStorage, 0)
storages = append(storages, raid...)
storages = append(storages, nonRaid...)
storages = append(storages, pcie...)
confs, err := s.GetDiskConfig()
if err != nil {
return nil, err
}
layouts, err := baremetal.CalculateLayout(confs, storages)
if err != nil {
return nil, err
}
tool, err := disktool.NewSSHPartitionTool(term, layouts)
if err != nil {
return nil, err
}
func (s *SBaremetalServer) DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error) {
// raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
// if err != nil {
// return nil, err
// }
// storages := make([]*baremetal.BaremetalStorage, 0)
// storages = append(storages, raid...)
// storages = append(storages, nonRaid...)
// storages = append(storages, pcie...)
// confs, err := s.GetDiskConfig()
// if err != nil {
// return nil, err
// }
// layouts, err := baremetal.CalculateLayout(confs, storages)
// if err != nil {
// return nil, err
// }
//
// tool, err := disktool.NewSSHPartitionTool(term, layouts)
// if err != nil {
// return nil, err
// }
disks, _ := s.desc.GetArray("disks")
if len(disks) == 0 {
@@ -2729,7 +2770,7 @@ func (s *SBaremetalServer) DoRebuildRootDisk(term *ssh.Client) ([]*disktool.Part
rootDisk := disks[0]
rootSize, _ := rootDisk.Int("size")
rd := tool.GetRootDisk()
err = s.doCreateRoot(term, rd.GetDevName())
err := s.doCreateRoot(term, rd.GetDevName())
if err != nil {
return nil, fmt.Errorf("Failed to create root: %v", err)
}
@@ -2797,7 +2838,7 @@ func (s *SBaremetalServer) SyncPartitionSize(term *ssh.Client, parts []*disktool
return disks, nil
}
func (s *SBaremetalServer) DoDeploy(term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) {
func (s *SBaremetalServer) DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error) {
publicKey := deployapi.GetKeys(data)
deploys, _ := data.GetArray("deploys")
password, _ := data.GetString("password")
@@ -2807,10 +2848,10 @@ func (s *SBaremetalServer) DoDeploy(term *ssh.Client, data jsonutils.JSONObject,
}
deployInfo := deployapi.NewDeployInfo(publicKey, deployapi.JsonDeploysToStructs(deploys),
password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser, false, "")
return s.deployFs(term, deployInfo)
return s.deployFs(tool, term, deployInfo)
}
func (s *SBaremetalServer) deployFs(term *ssh.Client, deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error) {
func (s *SBaremetalServer) deployFs(tool *disktool.SSHPartitionTool, term *ssh.Client, deployInfo *deployapi.DeployInfo) (jsonutils.JSONObject, error) {
raid, nonRaid, pcie, err := detect_storages.DetectStorageInfo(term, false)
if err != nil {
return nil, err
@@ -2827,7 +2868,7 @@ func (s *SBaremetalServer) deployFs(term *ssh.Client, deployInfo *deployapi.Depl
if err != nil {
return nil, err
}
rootDev, rootfs, err := sshpart.MountSSHRootfs(term, layouts)
rootDev, rootfs, err := sshpart.MountSSHRootfs(tool, term, layouts)
if err != nil {
return nil, fmt.Errorf("Find rootfs error: %s", err)
}
+3 -3
View File
@@ -52,7 +52,7 @@ func (self *SBaremetalServerCreateTask) RemoveEFIOSEntry() bool {
func (self *SBaremetalServerCreateTask) DoDeploys(term *ssh.Client) (jsonutils.JSONObject, error) {
// Build raid
err := self.Baremetal.GetServer().DoDiskConfig(term)
tool, err := self.Baremetal.GetServer().DoDiskConfig(term)
if err != nil {
return nil, self.onError(term, err)
}
@@ -61,7 +61,7 @@ func (self *SBaremetalServerCreateTask) DoDeploys(term *ssh.Client) (jsonutils.J
return nil, self.onError(term, err)
}
time.Sleep(2 * time.Second)
parts, err := self.Baremetal.GetServer().DoPartitionDisk(term)
parts, err := self.Baremetal.GetServer().DoPartitionDisk(tool, term)
if err != nil {
return nil, self.onError(term, err)
}
@@ -73,7 +73,7 @@ func (self *SBaremetalServerCreateTask) DoDeploys(term *ssh.Client) (jsonutils.J
data.Add(jsonutils.Marshal(disks), "disks")
rootImageId := self.Baremetal.GetServer().GetRootTemplateId()
if len(rootImageId) > 0 {
deployInfo, err := self.Baremetal.GetServer().DoDeploy(term, self.data, true)
deployInfo, err := self.Baremetal.GetServer().DoDeploy(tool, term, self.data, true)
if err != nil {
return nil, self.onError(term, err)
}
+6 -1
View File
@@ -16,6 +16,7 @@ package tasks
import (
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/ssh"
@@ -48,5 +49,9 @@ func (self *SBaremetalServerDeployTask) RemoveEFIOSEntry() bool {
}
func (self *SBaremetalServerDeployTask) DoDeploys(term *ssh.Client) (jsonutils.JSONObject, error) {
return self.Baremetal.GetServer().DoDeploy(term, self.data, false)
tool, err := self.Baremetal.GetServer().NewConfigedSSHPartitionTool(term)
if err != nil {
return nil, errors.Wrap(err, "NewConfigedSSHPartitionTool")
}
return self.Baremetal.GetServer().DoDeploy(tool, term, self.data, false)
}
+7 -2
View File
@@ -18,6 +18,7 @@ import (
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/ssh"
@@ -50,7 +51,11 @@ func (self *SBaremetalServerRebuildTask) RemoveEFIOSEntry() bool {
}
func (self *SBaremetalServerRebuildTask) DoDeploys(term *ssh.Client) (jsonutils.JSONObject, error) {
parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(term)
tool, err := self.Baremetal.GetServer().NewConfigedSSHPartitionTool(term)
if err != nil {
return nil, errors.Wrap(err, "NewConfigedSSHPartitionTool")
}
parts, err := self.Baremetal.GetServer().DoRebuildRootDisk(tool, term)
if err != nil {
return nil, fmt.Errorf("Rebuild root disk: %v", err)
}
@@ -60,7 +65,7 @@ func (self *SBaremetalServerRebuildTask) DoDeploys(term *ssh.Client) (jsonutils.
}
data := jsonutils.NewDict()
data.Add(jsonutils.NewArray(disks...), "disks")
deployInfo, err := self.Baremetal.GetServer().DoDeploy(term, self.data, true)
deployInfo, err := self.Baremetal.GetServer().DoDeploy(tool, term, self.data, true)
if err != nil {
return nil, fmt.Errorf("DoDeploy: %v", err)
}
+5 -4
View File
@@ -29,12 +29,13 @@ type IBaremetalServer interface {
GetId() string
RemoveDesc()
DoDiskUnconfig(term *ssh.Client) error
DoDiskConfig(term *ssh.Client) error
DoDiskConfig(term *ssh.Client) (*disktool.SSHPartitionTool, error)
DoEraseDisk(term *ssh.Client) error
DoPartitionDisk(term *ssh.Client) ([]*disktool.Partition, error)
DoRebuildRootDisk(term *ssh.Client) ([]*disktool.Partition, error)
DoPartitionDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error)
NewConfigedSSHPartitionTool(term *ssh.Client) (*disktool.SSHPartitionTool, error)
DoRebuildRootDisk(tool *disktool.SSHPartitionTool, term *ssh.Client) ([]*disktool.Partition, error)
SyncPartitionSize(term *ssh.Client, parts []*disktool.Partition) ([]jsonutils.JSONObject, error)
DoDeploy(term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error)
DoDeploy(tool *disktool.SSHPartitionTool, term *ssh.Client, data jsonutils.JSONObject, isInit bool) (jsonutils.JSONObject, error)
SaveDesc(desc jsonutils.JSONObject) error
GetNics() []types.SServerNic
GetNicByMac(mac net.HardwareAddr) *types.SNic
+7 -3
View File
@@ -19,9 +19,8 @@ import (
"math"
"strings"
"github.com/pkg/errors"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
@@ -612,8 +611,13 @@ func (tool *PartitionTool) Disks() []*DiskPartitions {
return tool.disks
}
func (tool *PartitionTool) parseLsDisk(lines []string, driver string) {
func (tool *PartitionTool) parseDiskInfo(lines []string, driver string) []*types.SDiskInfo {
disks := sysutils.ParseDiskInfo(lines, driver)
return disks
}
func (tool *PartitionTool) parseLsDisk(lines []string, driver string) {
disks := tool.parseDiskInfo(lines, driver)
if len(disks) == 0 {
return
}
@@ -183,6 +183,10 @@ func (ada *AdaptecRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) er
return nil
}
func (r *AdaptecRaidAdaptor) PostBuildRaid() error {
return nil
}
func (ada *AdaptecRaidAdaptor) getInitializeCmd(args ...string) string {
newArgs := []string{"TASK", "START", fmt.Sprintf("%d", ada.GetIndex()), "DEVICE"}
newArgs = append(newArgs, args...)
+15 -2
View File
@@ -17,10 +17,9 @@ package drivers
import (
"fmt"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
@@ -149,6 +148,20 @@ func buildRaid(driver raid.IRaidDriver, adapter raid.IRaidAdapter, confs []*api.
return fmt.Errorf("Build raw disks: %v", err)
}
}
if err := adapter.PostBuildRaid(); err != nil {
return errors.Wrap(err, "Post build raid")
}
return nil
}
func PostBuildRaid(driver raid.IRaidDriver, adapterIdx int) error {
for _, a := range driver.GetAdapters() {
if a.GetIndex() == adapterIdx {
if err := a.PostBuildRaid(); err != nil {
return errors.Wrap(err, "PostBuildRaid")
}
}
}
return nil
}
@@ -130,6 +130,10 @@ func (adapter *HPSARaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) e
return nil
}
func (adapter *HPSARaidAdaptor) PostBuildRaid() error {
return nil
}
func (adapter *HPSARaidAdaptor) ParsePhyDevs() error {
parseByCmd := func(cmd string, isRotate bool) error {
ret, err := adapter.raid.term.Run(cmd)
+1
View File
@@ -42,6 +42,7 @@ type IRaidAdapter interface {
BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
BuildNoneRaid(devs []*baremetal.BaremetalStorage) error
PostBuildRaid() error
}
type IExecTerm interface {
@@ -168,6 +168,10 @@ func (r *sRaidAdaptor) PreBuildRaid(_ []*compute.BaremetalDiskConfig) error {
return nil
}
func (r *sRaidAdaptor) PostBuildRaid() error {
return nil
}
func (r *sRaidAdaptor) ClearJBODDisks() {
r.iAdaptor.ClearJBODDisks(r.devs)
}
+4 -3
View File
@@ -173,9 +173,10 @@ func storcliBuildRaid(
if err != nil {
return errors.Wrapf(err, "build raid %d", level)
}
log.Infof("_storcliBuildRaid command: %s", cmd)
_, err = term.Run(cmd)
return err
if _, err := term.Run(cmd); err != nil {
return err
}
return nil
}
func conf2ParamsStorcliSize(conf *api.BaremetalDiskConfig) []string {
+70 -188
View File
@@ -20,7 +20,6 @@ import (
"strconv"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
@@ -461,17 +460,49 @@ func (adapter *MegaRaidAdaptor) getMegacliLogicVolumes() ([]*raiddrivers.RaidLog
return adapter.parseLogicVolumes(ret)
}
// 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) {
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)
lvs, err := adapter.getStorcliLogicVolumsV2()
if err != nil {
return nil, err
}
return lvs, nil
ret := make([]*raiddrivers.RaidLogicalVolume, len(lvs))
for i := range lvs {
lv := lvs[i]
ret[i] = &raiddrivers.RaidLogicalVolume{
Index: i,
Adapter: adapter.index,
BlockDev: lv.GetOSDevice(),
IsSSD: tristate.NewFromBool(lv.IsSSD()),
}
}
return ret, nil
}
func (adapter *MegaRaidAdaptor) getStorcliLogicVolumsV2() ([]*StorcliLogicalVolume, error) {
cmd := GetCommand2(fmt.Sprintf("/c%d/vall", adapter.index), "show", "all", "J")
ret, err := adapter.remoteRun(cmd)
if err != nil {
return nil, fmt.Errorf("getStorcliLogicVolumsV2 error: %v", err)
}
output := strings.Join(ret, "\n")
lvs, err := parseStorcliLVs(output)
if err != nil {
return nil, errors.Wrap(err, "parseStorcliLVs")
}
return lvs.GetLogicalVolumes(adapter.index)
}
var storcliLVRegexp = regexp.MustCompile(`^(?P<dg>\d+)\/(?P<vd>\d+)\s+(?P<type>RAID\d+).*`)
@@ -543,6 +574,32 @@ func (adapter *MegaRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) e
return nil
}
func (adapter *MegaRaidAdaptor) PostBuildRaid() error {
// sync rotational of logical block device
if err := adapter.storcliSyncBlockDeviceAttrs(); err != nil {
log.Warningf("adapter %d storcliSyncBlockDeviceAttrs: %v", adapter.index, err)
}
return nil
}
func (adapter *MegaRaidAdaptor) storcliSyncBlockDeviceAttrs() error {
lvs, err := adapter.getStorcliLogicVolumsV2()
if err != nil {
return errors.Wrap(err, "getStorcliLogicVolumsV2")
}
for _, lv := range lvs {
if !lv.IsSSD() {
continue
}
// e.g: echo 0 | tee /sys/block/sda/queue/rotational if logical volume is SSD
cmd := fmt.Sprintf("echo 0 | tee %s", lv.GetSysBlockRotationalPath())
if out, err := adapter.remoteRun(cmd); err != nil {
return errors.Wrapf(err, "%s out %v", cmd, out)
}
}
return nil
}
func conf2Params(conf *api.BaremetalDiskConfig) []string {
params := []string{}
if conf.WT != nil {
@@ -633,10 +690,13 @@ func (adapter *MegaRaidAdaptor) megacliBuildRaid10(devs []*baremetal.BaremetalSt
}
func (adapter *MegaRaidAdaptor) storcliBuildRaid(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig, level uint) error {
return storcliBuildRaid(
if err := storcliBuildRaid(
adapter.GetStorcliCommand,
adapter.getTerm(),
devs, conf, level)
devs, conf, level); err != nil {
return err
}
return nil
}
func (adapter *MegaRaidAdaptor) megacliBuildRaid(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig, level uint) error {
@@ -689,184 +749,6 @@ func (adapter *MegaRaidAdaptor) BuildNoneRaid(devs []*baremetal.BaremetalStorage
return cliBuildRaid(devs, nil, adapter.megacliBuildNoRaid, adapter.storcliBuildNoRaid)
}
type StorcliAdaptor struct {
Controller int
isSNEmpty bool
sn string
name string
busNumber string
deviceNumber string
funcNumber string
}
func newStorcliAdaptor() *StorcliAdaptor {
return &StorcliAdaptor{
Controller: -1,
isSNEmpty: false,
sn: "",
name: "",
busNumber: "",
deviceNumber: "",
funcNumber: "",
}
}
func (a StorcliAdaptor) key() string {
return a.name + a.sn
}
func (a *StorcliAdaptor) isComplete() bool {
if a.isSNEmpty {
return a.Controller >= 0 && a.name != "" && a.isPciInfoFilled()
}
return a.Controller >= 0 && a.name != "" && a.sn != "" && a.isPciInfoFilled()
}
func (a *StorcliAdaptor) isPciInfoFilled() bool {
return a.busNumber != "" && a.deviceNumber != "" && a.funcNumber != ""
}
func parseLineForStorcli(a *StorcliAdaptor, l string) {
controllerKey := "Controller"
productNameKey := "Product Name"
snKey := "Serial Number"
busNumber := "Bus Number"
devNumber := "Device Number"
funcNumber := "Function Number"
if !regexp.MustCompile(fmt.Sprintf("^(%s|%s|%s|%s|%s|%s)\\s*=", controllerKey, productNameKey, snKey, busNumber, devNumber, funcNumber)).Match([]byte(l)) {
return
}
parts := strings.Split(l, "=")
if len(parts) != 2 {
return
}
trimBeginEndSpace := func(s string) string {
return strings.TrimLeft(strings.TrimRight(s, " "), " ")
}
key := trimBeginEndSpace(parts[0])
val := trimBeginEndSpace(parts[1])
if key == snKey && val == "" {
a.isSNEmpty = true
return
}
switch key {
case controllerKey:
a.Controller, _ = strconv.Atoi(val)
case snKey:
a.sn = val
case productNameKey:
a.name = val
case busNumber:
a.busNumber = fmt.Sprintf("0%s", val)
case devNumber:
a.deviceNumber = fmt.Sprintf("0%s", val)
case funcNumber:
a.funcNumber = val
}
}
func (a *StorcliAdaptor) parseLine(l string) {
parseLineForStorcli(a, l)
}
func (a *StorcliAdaptor) String() string {
return fmt.Sprintf("{controller: %d, isSNEmpty: %v, sn: %q, name: %s}", a.Controller, a.isSNEmpty, a.sn, a.name)
}
type StorcliControllersInfo struct {
Controllers []*StorcliControllerInfo `json:"Controllers"`
}
type StorcliControllerInfo struct {
CommandStatus struct {
CliVersion string `json:"CLI Version"`
OperatingSystem string `json:"Operating system"`
Controller int `json:"Controller"`
Status string `json:"Status"`
} `json:"Command Status"`
ResponseData StorcliControllerData `json:"Response Data"`
}
type StorcliControllerData struct {
Info []*StorcliPhysicalDrive `json:"Drive Information"`
}
type StorcliPhysicalDrive struct {
EnclosureIdSlotNo string `json:"EID:Slt"`
DeviceId string `json:"DID"`
State string `json:"State"`
DriveGroup string `json:"DG"`
Size string `json:"Size"`
Interface string `json:"Intf"`
MediaType string `json:"Med"`
SelfEncryptiveDrive string `json:"SED"`
ProtectionInfo string `json:"PI"`
SectorSize string `json:"SeSz"`
Model string `json:"Model"`
Spun string `json:"Sp"`
Type string `json:"Type"`
}
func (d *StorcliPhysicalDrive) toMegaraidDev() (*MegaRaidPhyDev, error) {
dev := NewMegaRaidPhyDev()
if err := dev.fillByStorcliPD(d); err != nil {
return nil, errors.Wrap(err, "fillByStorcliPD")
}
return dev, nil
}
// parseStorcliControllers parse command `storecli64 /c0/eall/sall show J` json output
func parseStorcliControllers(jsonStr string) (*StorcliControllersInfo, error) {
obj, err := jsonutils.ParseString(jsonStr)
if err != nil {
return nil, err
}
info := new(StorcliControllersInfo)
if err := obj.Unmarshal(info); err != nil {
return nil, err
}
return info, nil
}
func (a *StorcliAdaptor) getPhyDevs(getCmd func(...string) string, term raid.IExecTerm) ([]*StorcliPhysicalDrive, error) {
cmd := getCmd(fmt.Sprintf("/c%d/eall/sall show J", a.Controller))
lines, err := term.Run(cmd)
if err != nil {
return nil, errors.Wrap(err, "Get storcli PDList json output")
}
jStr := strings.Join(lines, "\n")
info, err := parseStorcliControllers(jStr)
if err != nil {
return nil, errors.Wrapf(err, "parseStorcliControllers by string %q", jStr)
}
if len(info.Controllers) != 1 {
return nil, errors.Errorf("Not matched storcli PD list: %s", jsonutils.Marshal(info).PrettyString())
}
return info.Controllers[0].ResponseData.Info, nil
}
func (a *StorcliAdaptor) getMegaPhyDevs(getCmd func(...string) string, term raid.IExecTerm) ([]*MegaRaidPhyDev, error) {
pdList, err := a.getPhyDevs(getCmd, term)
if err != nil {
return nil, errors.Wrap(err, "storcli getPhyDevs")
}
ret := make([]*MegaRaidPhyDev, len(pdList))
for i, pd := range pdList {
dev, err := pd.toMegaraidDev()
if err != nil {
return nil, errors.Wrapf(err, "toMegaraidDev %s", jsonutils.Marshal(pd))
}
ret[i] = dev
}
return ret, nil
}
func (raid *MegaRaid) GetStorcliAdaptor() ([]*StorcliAdaptor, map[string]*StorcliAdaptor, error) {
ret := make(map[string]*StorcliAdaptor)
cmd := GetCommand2("/call", "show", "|", "grep", "-iE", `'^(Controller|Product Name|Serial Number|Bus Number|Device Number|Function Number)\s='`)
@@ -138,212 +138,6 @@ func TestParseLineForStorcli(t *testing.T) {
}
}
func Test_parseStorcliControllers(t *testing.T) {
input := `
{
"Controllers":[
{
"Command Status" : {
"CLI Version" : "007.1907.0000.0000 Sep 13, 2021",
"Operating system" : "Linux 5.14.0-4-arm64",
"Controller" : 0,
"Status" : "Success",
"Description" : "Show Drive Information Succeeded."
},
"Response Data" : {
"Drive Information" : [
{
"EID:Slt" : "65:0",
"DID" : 6,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:1",
"DID" : 8,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:2",
"DID" : 9,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:3",
"DID" : 7,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:4",
"DID" : 14,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:5",
"DID" : 13,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:6",
"DID" : 19,
"State" : "UGood",
"DG" : "F",
"Size" : "1.745 TB",
"Intf" : "SATA",
"Med" : "SSD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "INTEL SSDSC2KB019T8",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:7",
"DID" : 20,
"State" : "JBOD",
"DG" : "-",
"Size" : "1.746 TB",
"Intf" : "SATA",
"Med" : "SSD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "INTEL SSDSC2KB019T8",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:9",
"DID" : 15,
"State" : "Onln",
"DG" : 1,
"Size" : "3.637 TB",
"Intf" : "SATA",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "MG04ACA400N",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:10",
"DID" : 17,
"State" : "Onln",
"DG" : 1,
"Size" : "3.637 TB",
"Intf" : "SATA",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "MG04ACA400N",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:11",
"DID" : 16,
"State" : "Onln",
"DG" : 1,
"Size" : "3.637 TB",
"Intf" : "SATA",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "MG04ACA400N",
"Sp" : "U",
"Type" : "-"
}
]
}
}
]
}
`
info, err := parseStorcliControllers(input)
if err != nil {
t.Fatalf("parseStorcliControllers error: %v", err)
}
assert := assert.New(t)
assert.Equal(1, len(info.Controllers))
assert.Equal("ST1200MM0009 ", info.Controllers[0].ResponseData.Info[0].Model)
assert.Equal("1.089 TB", info.Controllers[0].ResponseData.Info[0].Size)
pds := info.Controllers[0].ResponseData.Info
for _, pd := range pds {
d, err := pd.toMegaraidDev()
if err != nil {
t.Fatalf("toMegaraidDev error: %v", err)
}
t.Logf("convert megaraid device: %#v", d)
}
}
func Test_parseStorcliLogicalVolumes(t *testing.T) {
type args struct {
adapter int
+354
View File
@@ -0,0 +1,354 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package megactl
import (
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
)
type StorcliAdaptor struct {
Controller int
isSNEmpty bool
sn string
name string
busNumber string
deviceNumber string
funcNumber string
}
func newStorcliAdaptor() *StorcliAdaptor {
return &StorcliAdaptor{
Controller: -1,
isSNEmpty: false,
sn: "",
name: "",
busNumber: "",
deviceNumber: "",
funcNumber: "",
}
}
func (a StorcliAdaptor) key() string {
return a.name + a.sn
}
func (a *StorcliAdaptor) isComplete() bool {
if a.isSNEmpty {
return a.Controller >= 0 && a.name != "" && a.isPciInfoFilled()
}
return a.Controller >= 0 && a.name != "" && a.sn != "" && a.isPciInfoFilled()
}
func (a *StorcliAdaptor) isPciInfoFilled() bool {
return a.busNumber != "" && a.deviceNumber != "" && a.funcNumber != ""
}
func parseLineForStorcli(a *StorcliAdaptor, l string) {
controllerKey := "Controller"
productNameKey := "Product Name"
snKey := "Serial Number"
busNumber := "Bus Number"
devNumber := "Device Number"
funcNumber := "Function Number"
if !regexp.MustCompile(fmt.Sprintf("^(%s|%s|%s|%s|%s|%s)\\s*=", controllerKey, productNameKey, snKey, busNumber, devNumber, funcNumber)).Match([]byte(l)) {
return
}
parts := strings.Split(l, "=")
if len(parts) != 2 {
return
}
trimBeginEndSpace := func(s string) string {
return strings.TrimLeft(strings.TrimRight(s, " "), " ")
}
key := trimBeginEndSpace(parts[0])
val := trimBeginEndSpace(parts[1])
if key == snKey && val == "" {
a.isSNEmpty = true
return
}
switch key {
case controllerKey:
a.Controller, _ = strconv.Atoi(val)
case snKey:
a.sn = val
case productNameKey:
a.name = val
case busNumber:
a.busNumber = fmt.Sprintf("0%s", val)
case devNumber:
a.deviceNumber = fmt.Sprintf("0%s", val)
case funcNumber:
a.funcNumber = val
}
}
func (a *StorcliAdaptor) parseLine(l string) {
parseLineForStorcli(a, l)
}
func (a *StorcliAdaptor) String() string {
return fmt.Sprintf("{controller: %d, isSNEmpty: %v, sn: %q, name: %s}", a.Controller, a.isSNEmpty, a.sn, a.name)
}
func (a *StorcliAdaptor) getPhyDevs(getCmd func(...string) string, term raid.IExecTerm) ([]*StorcliPhysicalDrive, error) {
cmd := getCmd(fmt.Sprintf("/c%d/eall/sall show J", a.Controller))
lines, err := term.Run(cmd)
if err != nil {
return nil, errors.Wrap(err, "Get storcli PDList json output")
}
jStr := strings.Join(lines, "\n")
info, err := parseStorcliControllers(jStr)
if err != nil {
return nil, errors.Wrapf(err, "parseStorcliControllers by string %q", jStr)
}
if len(info.Controllers) != 1 {
return nil, errors.Errorf("Not matched storcli PD list: %s", jsonutils.Marshal(info).PrettyString())
}
return info.Controllers[0].ResponseData.Info, nil
}
func (a *StorcliAdaptor) getMegaPhyDevs(getCmd func(...string) string, term raid.IExecTerm) ([]*MegaRaidPhyDev, error) {
pdList, err := a.getPhyDevs(getCmd, term)
if err != nil {
return nil, errors.Wrap(err, "storcli getPhyDevs")
}
ret := make([]*MegaRaidPhyDev, len(pdList))
for i, pd := range pdList {
dev, err := pd.toMegaraidDev()
if err != nil {
return nil, errors.Wrapf(err, "toMegaraidDev %s", jsonutils.Marshal(pd))
}
ret[i] = dev
}
return ret, nil
}
type StorcliControllersInfo struct {
Controllers []*StorcliControllerInfo `json:"Controllers"`
}
type StorcliControllerInfo struct {
CommandStatus struct {
CliVersion string `json:"CLI Version"`
OperatingSystem string `json:"Operating system"`
Controller int `json:"Controller"`
Status string `json:"Status"`
} `json:"Command Status"`
ResponseData StorcliControllerData `json:"Response Data"`
}
type StorcliControllerData struct {
Info []*StorcliPhysicalDrive `json:"Drive Information"`
}
type StorcliPhysicalDrive struct {
EnclosureIdSlotNo string `json:"EID:Slt"`
DeviceId string `json:"DID"`
State string `json:"State"`
DriveGroup string `json:"DG"`
Size string `json:"Size"`
Interface string `json:"Intf"`
MediaType string `json:"Med"`
SelfEncryptiveDrive string `json:"SED"`
ProtectionInfo string `json:"PI"`
SectorSize string `json:"SeSz"`
Model string `json:"Model"`
Spun string `json:"Sp"`
Type string `json:"Type"`
}
func (d *StorcliPhysicalDrive) toMegaraidDev() (*MegaRaidPhyDev, error) {
dev := NewMegaRaidPhyDev()
if err := dev.fillByStorcliPD(d); err != nil {
return nil, errors.Wrap(err, "fillByStorcliPD")
}
return dev, nil
}
// parseStorcliControllers parse command `storecli64 /c0/eall/sall show J` json output
func parseStorcliControllers(jsonStr string) (*StorcliControllersInfo, error) {
obj, err := jsonutils.ParseString(jsonStr)
if err != nil {
return nil, err
}
info := new(StorcliControllersInfo)
if err := obj.Unmarshal(info); err != nil {
return nil, err
}
return info, nil
}
type StorcliLogicalVolumes struct {
data jsonutils.JSONObject
}
func parseStorcliLVs(jsonStr string) (*StorcliLogicalVolumes, error) {
obj, err := jsonutils.ParseString(jsonStr)
if err != nil {
return nil, err
}
return &StorcliLogicalVolumes{
data: obj,
}, nil
}
func (lvs *StorcliLogicalVolumes) controllersData() ([]jsonutils.JSONObject, error) {
data, err := lvs.data.GetArray("Controllers")
if err != nil {
return nil, errors.Wrap(err, "Get Controllers")
}
return data, nil
}
func (lvs *StorcliLogicalVolumes) responseData(controller int) (*jsonutils.JSONDict, error) {
cData, err := lvs.controllersData()
if err != nil {
return nil, errors.Wrap(err, "controllersData")
}
data, err := cData[controller].Get("Response Data")
if err != nil {
return nil, errors.Wrap(err, "Get 'Response Data")
}
return data.(*jsonutils.JSONDict), nil
}
type StorcliLogicalVolumePD struct {
// "EID:Slt": "8:0"
EIDSlt string `json:"EID:Slt"`
// "Size": "446.625GB"
Size string `json:"Size"`
// "Intf": "SATA"
Intf string `json:"Intf"`
// "MED": "SSD"
Med string `json:"Med"`
// "Model": "SAMSUNG MZ7LH480HAHQ-00005"
Model string `json:"Model"`
}
type StorcliLogicalVolumeProperties struct {
// "Strip Size": "256 KB"
StripSize string `json:"Strip Size"`
// "OS Drive Name": "/dev/sda"
DeviceName string `json:"OS Drive Name"`
}
type StorcliLogicalVolume struct {
// Name format "/c0/v0"
Name string
// "TYPE": "RAID0"
Type string `json:"Type"`
// "DG/VD": "0/0"
DGVD string `json:"DG/VD"`
// "Size": "446.625GB"
Size string `json:"Size"`
// PDs for VD
PDs []*StorcliLogicalVolumePD
// Properties
Properties *StorcliLogicalVolumeProperties
}
func (lvs *StorcliLogicalVolumes) GetLogicalVolumes(controller int) ([]*StorcliLogicalVolume, error) {
data, err := lvs.responseData(controller)
if err != nil {
if errors.Cause(err) == jsonutils.ErrJsonDictKeyNotFound {
return nil, nil
}
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
}
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.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
}
func (lv *StorcliLogicalVolume) IsSSD() bool {
isSSD := true
for _, pd := range lv.PDs {
if strings.ToLower(pd.Med) != "ssd" {
return false
}
}
return isSSD
}
func (lv *StorcliLogicalVolume) GetOSDevice() string {
return lv.Properties.DeviceName
}
func (lv *StorcliLogicalVolume) GetSysBlockRotationalPath() string {
dev := filepath.Base(lv.GetOSDevice())
return filepath.Join("/sys/block/", dev, "/queue/rotational")
}
@@ -0,0 +1,667 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package megactl
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test_parseStorcliControllers(t *testing.T) {
input := `
{
"Controllers":[
{
"Command Status" : {
"CLI Version" : "007.1907.0000.0000 Sep 13, 2021",
"Operating system" : "Linux 5.14.0-4-arm64",
"Controller" : 0,
"Status" : "Success",
"Description" : "Show Drive Information Succeeded."
},
"Response Data" : {
"Drive Information" : [
{
"EID:Slt" : "65:0",
"DID" : 6,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:1",
"DID" : 8,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:2",
"DID" : 9,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:3",
"DID" : 7,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:4",
"DID" : 14,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:5",
"DID" : 13,
"State" : "Onln",
"DG" : 0,
"Size" : "1.089 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0009 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:6",
"DID" : 19,
"State" : "UGood",
"DG" : "F",
"Size" : "1.745 TB",
"Intf" : "SATA",
"Med" : "SSD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "INTEL SSDSC2KB019T8",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:7",
"DID" : 20,
"State" : "JBOD",
"DG" : "-",
"Size" : "1.746 TB",
"Intf" : "SATA",
"Med" : "SSD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "INTEL SSDSC2KB019T8",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:9",
"DID" : 15,
"State" : "Onln",
"DG" : 1,
"Size" : "3.637 TB",
"Intf" : "SATA",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "MG04ACA400N",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:10",
"DID" : 17,
"State" : "Onln",
"DG" : 1,
"Size" : "3.637 TB",
"Intf" : "SATA",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "MG04ACA400N",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "65:11",
"DID" : 16,
"State" : "Onln",
"DG" : 1,
"Size" : "3.637 TB",
"Intf" : "SATA",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "MG04ACA400N",
"Sp" : "U",
"Type" : "-"
}
]
}
}
]
}
`
info, err := parseStorcliControllers(input)
if err != nil {
t.Fatalf("parseStorcliControllers error: %v", err)
}
assert := assert.New(t)
assert.Equal(1, len(info.Controllers))
assert.Equal("ST1200MM0009 ", info.Controllers[0].ResponseData.Info[0].Model)
assert.Equal("1.089 TB", info.Controllers[0].ResponseData.Info[0].Size)
pds := info.Controllers[0].ResponseData.Info
for _, pd := range pds {
d, err := pd.toMegaraidDev()
if err != nil {
t.Fatalf("toMegaraidDev error: %v", err)
}
t.Logf("convert megaraid device: %#v", d)
}
}
func TestStorcliLogicalVolumes_GetLogicalVolumes(t *testing.T) {
input := `
{
"Controllers":[
{
"Command Status" : {
"CLI Version" : "007.1907.0000.0000 Sep 13, 2021",
"Operating system" : "Linux 5.14.0-4-arm64",
"Controller" : 0,
"Status" : "Success",
"Description" : "None"
},
"Response Data" : {
"/c0/v0" : [
{
"DG/VD" : "0/0",
"TYPE" : "RAID1",
"State" : "Optl",
"Access" : "RW",
"Consist" : "No",
"Cache" : "RWBD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "446.625 GB",
"Name" : ""
}
],
"PDs for VD 0" : [
{
"EID:Slt" : "8:0",
"DID" : 16,
"State" : "Onln",
"DG" : 0,
"Size" : "446.625 GB",
"Intf" : "SATA",
"Med" : "SSD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "SAMSUNG MZ7LH480HAHQ-00005",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "8:1",
"DID" : 17,
"State" : "Onln",
"DG" : 0,
"Size" : "446.625 GB",
"Intf" : "SATA",
"Med" : "SSD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "SAMSUNG MZ7LH480HAHQ-00005",
"Sp" : "U",
"Type" : "-"
}
],
"VD0 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 936640512,
"VD has Emulated PD" : "Yes",
"Span Depth" : 1,
"Number of Drives Per Span" : 2,
"Write Cache(initial setting)" : "WriteBack",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sda",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:23 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372bf4d29f6a7",
"Unmap Enabled" : "N/A"
},
"/c0/v1" : [
{
"DG/VD" : "1/1",
"TYPE" : "RAID1",
"State" : "Optl",
"Access" : "RW",
"Consist" : "No",
"Cache" : "RWBD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "558.406 GB",
"Name" : ""
}
],
"PDs for VD 1" : [
{
"EID:Slt" : "8:2",
"DID" : 15,
"State" : "Onln",
"DG" : 1,
"Size" : "558.406 GB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST600MP0006 ",
"Sp" : "U",
"Type" : "-"
},
{
"EID:Slt" : "8:3",
"DID" : 12,
"State" : "Onln",
"DG" : 1,
"Size" : "558.406 GB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST600MP0006 ",
"Sp" : "U",
"Type" : "-"
}
],
"VD1 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 1171062784,
"VD has Emulated PD" : "No",
"Span Depth" : 1,
"Number of Drives Per Span" : 2,
"Write Cache(initial setting)" : "WriteBack",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sdb",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:24 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372c04d2fb6b9",
"Unmap Enabled" : "N/A"
},
"/c0/v2" : [
{
"DG/VD" : "2/2",
"TYPE" : "RAID0",
"State" : "Optl",
"Access" : "RW",
"Consist" : "Yes",
"Cache" : "NRWTD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "1.090 TB",
"Name" : ""
}
],
"PDs for VD 2" : [
{
"EID:Slt" : "8:4",
"DID" : 14,
"State" : "Onln",
"DG" : 2,
"Size" : "1.090 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0129 ",
"Sp" : "U",
"Type" : "-"
}
],
"VD2 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 2343174144,
"VD has Emulated PD" : "Yes",
"Span Depth" : 1,
"Number of Drives Per Span" : 1,
"Write Cache(initial setting)" : "WriteThrough",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sdc",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:24 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372c04d3ad143",
"Unmap Enabled" : "N/A"
},
"/c0/v3" : [
{
"DG/VD" : "3/3",
"TYPE" : "RAID0",
"State" : "Optl",
"Access" : "RW",
"Consist" : "Yes",
"Cache" : "NRWTD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "1.090 TB",
"Name" : ""
}
],
"PDs for VD 3" : [
{
"EID:Slt" : "8:5",
"DID" : 10,
"State" : "Onln",
"DG" : 3,
"Size" : "1.090 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0129 ",
"Sp" : "U",
"Type" : "-"
}
],
"VD3 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 2343174144,
"VD has Emulated PD" : "Yes",
"Span Depth" : 1,
"Number of Drives Per Span" : 1,
"Write Cache(initial setting)" : "WriteThrough",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sdd",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:25 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372c14d48b67e",
"Unmap Enabled" : "N/A"
},
"/c0/v4" : [
{
"DG/VD" : "4/4",
"TYPE" : "RAID0",
"State" : "Optl",
"Access" : "RW",
"Consist" : "Yes",
"Cache" : "NRWTD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "1.090 TB",
"Name" : ""
}
],
"PDs for VD 4" : [
{
"EID:Slt" : "8:6",
"DID" : 9,
"State" : "Onln",
"DG" : 4,
"Size" : "1.090 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0129 ",
"Sp" : "U",
"Type" : "-"
}
],
"VD4 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 2343174144,
"VD has Emulated PD" : "Yes",
"Span Depth" : 1,
"Number of Drives Per Span" : 1,
"Write Cache(initial setting)" : "WriteThrough",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sde",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:26 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372c24d57b796",
"Unmap Enabled" : "N/A"
},
"/c0/v5" : [
{
"DG/VD" : "5/5",
"TYPE" : "RAID0",
"State" : "Optl",
"Access" : "RW",
"Consist" : "Yes",
"Cache" : "NRWTD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "1.090 TB",
"Name" : ""
}
],
"PDs for VD 5" : [
{
"EID:Slt" : "8:7",
"DID" : 11,
"State" : "Onln",
"DG" : 5,
"Size" : "1.090 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0129 ",
"Sp" : "U",
"Type" : "-"
}
],
"VD5 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 2343174144,
"VD has Emulated PD" : "Yes",
"Span Depth" : 1,
"Number of Drives Per Span" : 1,
"Write Cache(initial setting)" : "WriteThrough",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sdf",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:27 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372c34d665ecf",
"Unmap Enabled" : "N/A"
},
"/c0/v6" : [
{
"DG/VD" : "6/6",
"TYPE" : "RAID0",
"State" : "Optl",
"Access" : "RW",
"Consist" : "Yes",
"Cache" : "NRWTD",
"Cac" : "-",
"sCC" : "ON",
"Size" : "1.090 TB",
"Name" : ""
}
],
"PDs for VD 6" : [
{
"EID:Slt" : "8:8",
"DID" : 13,
"State" : "Onln",
"DG" : 6,
"Size" : "1.090 TB",
"Intf" : "SAS",
"Med" : "HDD",
"SED" : "N",
"PI" : "N",
"SeSz" : "512B",
"Model" : "ST1200MM0129 ",
"Sp" : "U",
"Type" : "-"
}
],
"VD6 Properties" : {
"Strip Size" : "256 KB",
"Number of Blocks" : 2343174144,
"VD has Emulated PD" : "Yes",
"Span Depth" : 1,
"Number of Drives Per Span" : 1,
"Write Cache(initial setting)" : "WriteThrough",
"Disk Cache Policy" : "Disk's Default",
"Encryption" : "None",
"Data Protection" : "Disabled",
"Active Operations" : "None",
"Exposed to OS" : "Yes",
"OS Drive Name" : "/dev/sdg",
"Creation Date" : "08-06-2022",
"Creation Time" : "02:46:28 PM",
"Emulation type" : "default",
"Cachebypass size" : "Cachebypass-64k",
"Cachebypass Mode" : "Cachebypass Intelligent",
"Is LD Ready for OS Requests" : "Yes",
"SCSI NAA Id" : "600605b010e943702a3372c44d751bab",
"Unmap Enabled" : "N/A"
}
}
}
]
}`
parser, err := parseStorcliLVs(input)
if err != nil {
t.Fatalf("parseStorcliLVs: %v", err)
}
lvs, err := parser.GetLogicalVolumes(0)
if err != nil {
t.Fatalf("GetLogicalVolumes: %v", err)
}
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)
}
+4
View File
@@ -209,6 +209,10 @@ func (adapter *MarvelRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig)
return nil
}
func (adapter *MarvelRaidAdaptor) PostBuildRaid() error {
return nil
}
func (adapter *MarvelRaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, _ *api.BaremetalDiskConfig) error {
pds := []string{}
for _, dev := range devs {
+1
View File
@@ -141,6 +141,7 @@ type RaidLogicalVolume struct {
Index int
Adapter int
BlockDev string
IsSSD tristate.TriState
}
func SGMap(term IExecTerm) ([]compute.SGMapItem, error) {
@@ -253,6 +253,10 @@ func (adapter *Mpt2SASRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig
return nil
}
func (adapter *Mpt2SASRaidAdaptor) PostBuildRaid() error {
return nil
}
func (adapter *Mpt2SASRaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
if len(conf.Size) > 1 {
return fmt.Errorf("Subdivide sub-size not supported")
+1 -1
View File
@@ -73,7 +73,7 @@ func (d *SGalaxyKylinRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics
}
func (c *SGalaxyKylinRootFs) EnableSerialConsole(rootFs IDiskPartition, sysInfo *jsonutils.JSONDict) error {
return c.enableSerialConsole(c, rootFs, sysInfo)
return c.enableSerialConsoleSystemd(rootFs)
}
func (c *SGalaxyKylinRootFs) DisableSerialConsole(rootFs IDiskPartition) error {
+6 -6
View File
@@ -582,12 +582,12 @@ func (p *SSHPartition) Zerofree() {
log.Warningf("zerofree should not called in ssh partition")
}
func MountSSHRootfs(term *ssh.Client, layouts []baremetal.Layout) (*SSHPartition, fsdriver.IRootFsDriver, error) {
tool, err := disktool.NewSSHPartitionTool(term, layouts)
if err != nil {
return nil, nil, err
}
tool.RetrievePartitionInfo()
func MountSSHRootfs(tool *disktool.SSHPartitionTool, term *ssh.Client, layouts []baremetal.Layout) (*SSHPartition, fsdriver.IRootFsDriver, error) {
// tool, err := disktool.NewSSHPartitionTool(term, layouts)
// if err != nil {
// return nil, nil, err
// }
// tool.RetrievePartitionInfo()
rootDisk := tool.GetRootDisk()
if err := rootDisk.ReInitInfo(); err != nil {
return nil, nil, errors.Wrapf(err, "Reinit root disk")