mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
fix(baremetal): storcli set sysblock rotational of SSD logical volume (#14424)
This commit is contained in:
+93
-52
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user