mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 02:37:24 +08:00
feat(baremetal): megaraid perccli supported
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/baremetal-base:v0.3.3-2-grub
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/baremetal-base:v0.3.3-2-grub-test
|
||||
|
||||
MAINTAINER "Zexi Li <lizexi@yunionyun.com>"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#FROM --platform=linux/amd64 registry.cn-beijing.aliyuncs.com/yunionio/centos-build:1.1-4 as build
|
||||
#RUN yum install -y https://iso.yunion.cn/vm-images/baremetal-pxerom-1.1.0-21092209.x86_64.rpm
|
||||
#RUN yum install -y http://192.168.23.50:8083/baremetal-pxerom-1.1.0-21092209.x86_64.rpm
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunionos:v0.1.1 as yunionos
|
||||
FROM registry.cn-beijing.aliyuncs.com/yunionio/yunionos:v0.1.1-test as yunionos
|
||||
|
||||
FROM centos:8 as grub-stage
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ WEBCONSOLE_BASE_VERSION = v0.2-1
|
||||
webconsole-base:
|
||||
$(DOCKER_BUILDX)/webconsole-base:$(WEBCONSOLE_BASE_VERSION) -f ./Dockerfile.webconsole-base .
|
||||
|
||||
BAREMETAL_BASE_VERSION = v0.3.3-2-grub
|
||||
BAREMETAL_BASE_VERSION = v0.3.3-2-grub-test
|
||||
|
||||
baremetal-base:
|
||||
$(DOCKER_BUILDX)/baremetal-base:$(BAREMETAL_BASE_VERSION) -f ./Dockerfile.baremetal-base .
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// 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 (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
)
|
||||
|
||||
func init() {
|
||||
raid.RegisterDriver(baremetal.DISK_DRIVER_MEGARAID, newRaid)
|
||||
}
|
||||
|
||||
type iDriver interface {
|
||||
GetName() string
|
||||
GetAdapterConstructCmd() string
|
||||
NewAdaptor(term raid.IExecTerm) iAdaptor
|
||||
ClearForeignState(term raid.IExecTerm) error
|
||||
}
|
||||
|
||||
type iAdaptor interface {
|
||||
ParseLine(line string)
|
||||
IsComplete() bool
|
||||
Key() string
|
||||
GetPhyDevs() ([]*MegaRaidPhyDev, error)
|
||||
ClearJBODDisks(devs []*MegaRaidPhyDev)
|
||||
|
||||
GetIndex() int
|
||||
GetLogicVolumes() ([]*raid.RaidLogicalVolume, error)
|
||||
RemoveLogicVolumes() error
|
||||
BuildRaid0(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error
|
||||
BuildRaid1(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error
|
||||
BuildRaid5(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error
|
||||
BuildRaid10(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error
|
||||
BuildNoneRaid(devs []*baremetal.BaremetalStorage) error
|
||||
}
|
||||
|
||||
type sRaid struct {
|
||||
driver iDriver
|
||||
term raid.IExecTerm
|
||||
adaptors []*sRaidAdaptor
|
||||
phyDevsCnt int
|
||||
}
|
||||
|
||||
func newRaid(term raid.IExecTerm) raid.IRaidDriver {
|
||||
perccliDrv := &sRaid{
|
||||
driver: newPerccliDriver(),
|
||||
term: term,
|
||||
adaptors: make([]*sRaidAdaptor, 0),
|
||||
}
|
||||
if err := perccliDrv.ParsePhyDevs(); err == nil && perccliDrv.phyDevsCnt > 0 {
|
||||
log.Infof("Use perccli driver, found %d pds", perccliDrv.phyDevsCnt)
|
||||
return perccliDrv
|
||||
} else {
|
||||
log.Warningf("perccli driver parse physical devices error: %v, %d pds, fallback to old megactl and storcli driver", err, perccliDrv.phyDevsCnt)
|
||||
return NewMegaRaid(term)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *sRaid) GetName() string {
|
||||
return baremetal.DISK_DRIVER_MEGARAID
|
||||
}
|
||||
|
||||
type sRaidAdaptor struct {
|
||||
iAdaptor
|
||||
|
||||
raid *sRaid
|
||||
devs []*MegaRaidPhyDev
|
||||
sn string
|
||||
name string
|
||||
busNumber string
|
||||
deviceNumber string
|
||||
funcNumber string
|
||||
// used by sg_map
|
||||
hostNum int
|
||||
//channelNum int
|
||||
}
|
||||
|
||||
func newRaidAdaptor(baseAda iAdaptor, raid *sRaid) *sRaidAdaptor {
|
||||
return &sRaidAdaptor{
|
||||
iAdaptor: baseAda,
|
||||
raid: raid,
|
||||
devs: make([]*MegaRaidPhyDev, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *sRaidAdaptor) AddPhyDev(dev *MegaRaidPhyDev) {
|
||||
a.devs = append(a.devs, dev)
|
||||
}
|
||||
|
||||
func (r *sRaid) ParsePhyDevs() error {
|
||||
adaptors, _, err := r.getAdaptor()
|
||||
r.phyDevsCnt = 0
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Get %q adaptor", r.driver.GetName())
|
||||
}
|
||||
r.adaptors = make([]*sRaidAdaptor, 0)
|
||||
for _, ada := range adaptors {
|
||||
devs, err := ada.GetPhyDevs()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Get %q adaptor physical devices")
|
||||
}
|
||||
nAda := newRaidAdaptor(ada, r)
|
||||
for i := range devs {
|
||||
nAda.AddPhyDev(devs[i])
|
||||
r.phyDevsCnt++
|
||||
}
|
||||
r.adaptors = append(r.adaptors, nAda)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sRaid) getAdaptor() ([]iAdaptor, map[string]iAdaptor, error) {
|
||||
ret := make(map[string]iAdaptor)
|
||||
cmd := r.driver.GetAdapterConstructCmd()
|
||||
lines, err := r.term.Run(cmd)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "Get storcli adapter")
|
||||
}
|
||||
adaptor := r.driver.NewAdaptor(r.term)
|
||||
list := make([]iAdaptor, 0)
|
||||
for _, l := range lines {
|
||||
adaptor.ParseLine(l)
|
||||
if adaptor.IsComplete() {
|
||||
ret[adaptor.Key()] = adaptor
|
||||
list = append(list, adaptor)
|
||||
adaptor = r.driver.NewAdaptor(r.term)
|
||||
}
|
||||
}
|
||||
return list, ret, nil
|
||||
}
|
||||
|
||||
func (r *sRaid) PreBuildRaid(_ []*compute.BaremetalDiskConfig, _ int) error {
|
||||
return r.driver.ClearForeignState(r.term)
|
||||
}
|
||||
|
||||
func (r *sRaid) GetAdapters() []raid.IRaidAdapter {
|
||||
ret := make([]raid.IRaidAdapter, len(r.adaptors))
|
||||
for i := range r.adaptors {
|
||||
ret[i] = r.adaptors[i]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *sRaidAdaptor) PreBuildRaid(_ []*compute.BaremetalDiskConfig) error {
|
||||
r.ClearJBODDisks()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sRaidAdaptor) ClearJBODDisks() {
|
||||
r.iAdaptor.ClearJBODDisks(r.devs)
|
||||
}
|
||||
|
||||
func (r *sRaidAdaptor) GetDevices() []*baremetal.BaremetalStorage {
|
||||
ret := []*baremetal.BaremetalStorage{}
|
||||
for idx, dev := range r.devs {
|
||||
ret = append(ret, dev.ToBaremetalStorage(idx))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *sRaid) CleanRaid() error {
|
||||
for _, ada := range r.adaptors {
|
||||
ada.ClearJBODDisks()
|
||||
ada.RemoveLogicVolumes()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
// 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"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
)
|
||||
|
||||
func storcliIsJBODEnabled(
|
||||
getCmd func(args ...string) (string, error),
|
||||
term raid.IExecTerm,
|
||||
) bool {
|
||||
cmd, err := getCmd("show", "jbod")
|
||||
if err != nil {
|
||||
log.Errorf("get storcli controller cmd: %v", err)
|
||||
return false
|
||||
}
|
||||
lines, err := term.Run(cmd)
|
||||
if err != nil {
|
||||
log.Errorf("storcliIsJBODEnabled error: %s", err)
|
||||
return false
|
||||
}
|
||||
for _, line := range lines {
|
||||
line = strings.ToLower(line)
|
||||
if strings.HasPrefix(line, "jbod") {
|
||||
data := strings.Split(line, " ")
|
||||
if strings.TrimSpace(data[len(data)-1]) == "on" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func storcliEnableJBOD(
|
||||
getCmd func(args ...string) (string, error),
|
||||
term raid.IExecTerm,
|
||||
enable bool) bool {
|
||||
val := "off"
|
||||
if enable {
|
||||
val = "on"
|
||||
}
|
||||
cmd, err := getCmd("set", fmt.Sprintf("jbod=%s", val), "force")
|
||||
if err != nil {
|
||||
log.Errorf("get storcli controller cmd: %v", err)
|
||||
return false
|
||||
}
|
||||
_, err = term.Run(cmd)
|
||||
if err != nil {
|
||||
log.Errorf("EnableJBOD %v fail: %v", enable, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func storcliBuildJBOD(
|
||||
getCmd func(args ...string) (string, error),
|
||||
term raid.IExecTerm,
|
||||
devs []*baremetal.BaremetalStorage) error {
|
||||
if !storcliIsJBODEnabled(getCmd, term) {
|
||||
storcliEnableJBOD(getCmd, term, true)
|
||||
storcliEnableJBOD(getCmd, term, false)
|
||||
storcliEnableJBOD(getCmd, term, true)
|
||||
}
|
||||
if !storcliIsJBODEnabled(getCmd, term) {
|
||||
return fmt.Errorf("JBOD not supported")
|
||||
}
|
||||
cmds := []string{}
|
||||
for _, d := range devs {
|
||||
// cmd := GetCommand2(fmt.Sprintf("/c%d/e%d/s%d", adapter.storcliIndex, d.Enclosure, d.Slot))
|
||||
cmd, err := getCmd()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "getCmd for dev %#v", d)
|
||||
}
|
||||
cmd = fmt.Sprintf("%s/e%d/s%d", d.Enclosure, d.Slot)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
log.Infof("storcliBuildJBOD cmds: %v", cmds)
|
||||
_, err := term.Run(cmds...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func storcliBuildNoRaid(
|
||||
getCmd func(args ...string) (string, error),
|
||||
term raid.IExecTerm,
|
||||
devs []*baremetal.BaremetalStorage) error {
|
||||
err := storcliBuildJBOD(getCmd, term, devs)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
log.Errorf("Try storcli build JBOD fail: %v", err)
|
||||
labels := []string{}
|
||||
for _, dev := range devs {
|
||||
labels = append(labels, GetSpecString(dev))
|
||||
}
|
||||
args := []string{
|
||||
"add", "vd", "each", "type=raid0",
|
||||
fmt.Sprintf("drives=%s", strings.Join(labels, ",")),
|
||||
"wt", "nora", "direct",
|
||||
}
|
||||
cmd, err := getCmd(args...)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "build none raid")
|
||||
}
|
||||
_, err = term.Run(cmd)
|
||||
return err
|
||||
}
|
||||
|
||||
func storcliClearJBODDisks(
|
||||
getCmd func(args ...string) (string, error),
|
||||
term raid.IExecTerm,
|
||||
devs []*MegaRaidPhyDev,
|
||||
) error {
|
||||
errs := make([]error, 0)
|
||||
for _, dev := range devs {
|
||||
cmd, err := getCmd()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get cmd error")
|
||||
}
|
||||
cmd = fmt.Sprintf("%s/e%d/s%d set good force", cmd, dev.enclosure, dev.slot)
|
||||
if _, err := term.Run(cmd); err != nil {
|
||||
err = errors.Wrapf(err, "Set PD good storcli cmd %v", cmd)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
func storcliBuildRaid(
|
||||
getCmd func(args ...string) (string, error),
|
||||
term raid.IExecTerm,
|
||||
devs []*baremetal.BaremetalStorage,
|
||||
conf *api.BaremetalDiskConfig,
|
||||
level uint,
|
||||
) error {
|
||||
args := []string{}
|
||||
args = append(args, "add", "vd", fmt.Sprintf("type=r%d", level))
|
||||
args = append(args, conf2ParamsStorcliSize(conf)...)
|
||||
labels := []string{}
|
||||
for _, dev := range devs {
|
||||
labels = append(labels, GetSpecString(dev))
|
||||
}
|
||||
args = append(args, fmt.Sprintf("drives=%s", strings.Join(labels, ",")))
|
||||
if level == 10 {
|
||||
args = append(args, "PDperArray=2")
|
||||
}
|
||||
args = append(args, conf2ParamsStorcli(conf)...)
|
||||
cmd, err := getCmd(args...)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "build raid %d", level)
|
||||
}
|
||||
log.Infof("_storcliBuildRaid command: %s", cmd)
|
||||
_, err = term.Run(cmd)
|
||||
return err
|
||||
}
|
||||
|
||||
func conf2ParamsStorcliSize(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
szStr := []string{}
|
||||
if len(conf.Size) > 0 {
|
||||
for _, sz := range conf.Size {
|
||||
szStr = append(szStr, fmt.Sprintf("%dMB", sz))
|
||||
}
|
||||
params = append(params, fmt.Sprintf("Size=%s", strings.Join(szStr, ",")))
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func conf2ParamsStorcli(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
if conf.WT != nil {
|
||||
if *conf.WT {
|
||||
params = append(params, "wt")
|
||||
} else {
|
||||
params = append(params, "wb")
|
||||
}
|
||||
}
|
||||
if conf.RA != nil {
|
||||
if *conf.RA {
|
||||
params = append(params, "ra")
|
||||
} else {
|
||||
params = append(params, "nora")
|
||||
}
|
||||
}
|
||||
if conf.Direct != nil {
|
||||
if *conf.Direct {
|
||||
params = append(params, "direct")
|
||||
} else {
|
||||
params = append(params, "cached")
|
||||
}
|
||||
}
|
||||
if conf.Cachedbadbbu != nil {
|
||||
if *conf.Cachedbadbbu {
|
||||
params = append(params, "CachedBadBBU")
|
||||
} else {
|
||||
params = append(params, "NoCachedBadBBU")
|
||||
}
|
||||
}
|
||||
if conf.Strip != nil {
|
||||
params = append(params, fmt.Sprintf("Strip=%d", *conf.Strip))
|
||||
}
|
||||
return params
|
||||
}
|
||||
@@ -543,54 +543,6 @@ func (adapter *MegaRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) conf2ParamsStorcliSize(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
szStr := []string{}
|
||||
if len(conf.Size) > 0 {
|
||||
for _, sz := range conf.Size {
|
||||
szStr = append(szStr, fmt.Sprintf("%dMB", sz))
|
||||
}
|
||||
params = append(params, fmt.Sprintf("Size=%s", strings.Join(szStr, ",")))
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) conf2ParamsStorcli(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
if conf.WT != nil {
|
||||
if *conf.WT {
|
||||
params = append(params, "wt")
|
||||
} else {
|
||||
params = append(params, "wb")
|
||||
}
|
||||
}
|
||||
if conf.RA != nil {
|
||||
if *conf.RA {
|
||||
params = append(params, "ra")
|
||||
} else {
|
||||
params = append(params, "nora")
|
||||
}
|
||||
}
|
||||
if conf.Direct != nil {
|
||||
if *conf.Direct {
|
||||
params = append(params, "direct")
|
||||
} else {
|
||||
params = append(params, "cached")
|
||||
}
|
||||
}
|
||||
if conf.Cachedbadbbu != nil {
|
||||
if *conf.Cachedbadbbu {
|
||||
params = append(params, "CachedBadBBU")
|
||||
} else {
|
||||
params = append(params, "NoCachedBadBBU")
|
||||
}
|
||||
}
|
||||
if conf.Strip != nil {
|
||||
params = append(params, fmt.Sprintf("Strip=%d", *conf.Strip))
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
func conf2Params(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
if conf.WT != nil {
|
||||
@@ -681,25 +633,10 @@ func (adapter *MegaRaidAdaptor) megacliBuildRaid10(devs []*baremetal.BaremetalSt
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig, level uint) error {
|
||||
args := []string{}
|
||||
args = append(args, "add", "vd", fmt.Sprintf("type=r%d", level))
|
||||
args = append(args, adapter.conf2ParamsStorcliSize(conf)...)
|
||||
labels := []string{}
|
||||
for _, dev := range devs {
|
||||
labels = append(labels, GetSpecString(dev))
|
||||
}
|
||||
args = append(args, fmt.Sprintf("drives=%s", strings.Join(labels, ",")))
|
||||
if level == 10 {
|
||||
args = append(args, "PDperArray=2")
|
||||
}
|
||||
args = append(args, adapter.conf2ParamsStorcli(conf)...)
|
||||
cmd, err := adapter.GetStorcliCommand(args...)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "build raid %d", level)
|
||||
}
|
||||
log.Infof("_storcliBuildRaid command: %s", cmd)
|
||||
_, err = adapter.remoteRun(cmd)
|
||||
return err
|
||||
return storcliBuildRaid(
|
||||
adapter.GetStorcliCommand,
|
||||
adapter.getTerm(),
|
||||
devs, conf, level)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig, level uint) error {
|
||||
@@ -897,9 +834,10 @@ func parseStorcliControllers(jsonStr string) (*StorcliControllersInfo, error) {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (a *StorcliAdaptor) getPhyDevs(raid *MegaRaid) ([]*StorcliPhysicalDrive, error) {
|
||||
cmd := GetCommand2(fmt.Sprintf("/c%d/eall/sall show J", a.Controller))
|
||||
lines, err := raid.term.Run(cmd)
|
||||
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))
|
||||
log.Errorf("----term %#v, cmd: %q", term, cmd)
|
||||
lines, err := term.Run(cmd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Get storcli PDList json output")
|
||||
}
|
||||
@@ -914,8 +852,8 @@ func (a *StorcliAdaptor) getPhyDevs(raid *MegaRaid) ([]*StorcliPhysicalDrive, er
|
||||
return info.Controllers[0].ResponseData.Info, nil
|
||||
}
|
||||
|
||||
func (a *StorcliAdaptor) getMegaPhyDevs(raid *MegaRaid) ([]*MegaRaidPhyDev, error) {
|
||||
pdList, err := a.getPhyDevs(raid)
|
||||
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")
|
||||
}
|
||||
@@ -976,27 +914,7 @@ func (adapter *MegaRaidAdaptor) GetStorcliCommand(args ...string) (string, error
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliIsJBODEnabled() bool {
|
||||
cmd, err := adapter.GetStorcliCommand("show", "jbod")
|
||||
if err != nil {
|
||||
log.Errorf("get storcli controller cmd: %v", err)
|
||||
return false
|
||||
}
|
||||
lines, err := adapter.remoteRun(cmd)
|
||||
if err != nil {
|
||||
log.Errorf("storcliIsJBODEnabled error: %s", err)
|
||||
return false
|
||||
}
|
||||
for _, line := range lines {
|
||||
line = strings.ToLower(line)
|
||||
if strings.HasPrefix(line, "jbod") {
|
||||
data := strings.Split(line, " ")
|
||||
if strings.TrimSpace(data[len(data)-1]) == "on" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
return storcliIsJBODEnabled(adapter.GetStorcliCommand, adapter.getTerm())
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliEnableJBOD(enable bool) bool {
|
||||
@@ -1018,48 +936,11 @@ func (adapter *MegaRaidAdaptor) storcliEnableJBOD(enable bool) bool {
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildJBOD(devs []*baremetal.BaremetalStorage) error {
|
||||
if !adapter.storcliIsJBODEnabled() {
|
||||
adapter.storcliEnableJBOD(true)
|
||||
adapter.storcliEnableJBOD(false)
|
||||
adapter.storcliEnableJBOD(true)
|
||||
}
|
||||
if !adapter.storcliIsJBODEnabled() {
|
||||
return fmt.Errorf("JBOD not supported")
|
||||
}
|
||||
cmds := []string{}
|
||||
for _, d := range devs {
|
||||
cmd := GetCommand2(fmt.Sprintf("/c%d/e%d/s%d", adapter.storcliIndex, d.Enclosure, d.Slot))
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
log.Infof("storcliBuildJBOD cmds: %v", cmds)
|
||||
_, err := adapter.remoteRun(cmds...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return storcliBuildJBOD(adapter.GetStorcliCommand, adapter.getTerm(), devs)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildNoRaid(devs []*baremetal.BaremetalStorage, _ *api.BaremetalDiskConfig) error {
|
||||
err := adapter.storcliBuildJBOD(devs)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
log.Errorf("Try storcli build JBOD fail: %v", err)
|
||||
labels := []string{}
|
||||
for _, dev := range devs {
|
||||
labels = append(labels, GetSpecString(dev))
|
||||
}
|
||||
args := []string{
|
||||
"add", "vd", "each", "type=raid0",
|
||||
fmt.Sprintf("drives=%s", strings.Join(labels, ",")),
|
||||
"wt", "nora", "direct",
|
||||
}
|
||||
cmd, err := adapter.GetStorcliCommand(args...)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "build none raid")
|
||||
}
|
||||
_, err = adapter.remoteRun(cmd)
|
||||
return err
|
||||
return storcliBuildNoRaid(adapter.GetStorcliCommand, adapter.getTerm(), devs)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildNoRaid(devs []*baremetal.BaremetalStorage, _ *api.BaremetalDiskConfig) error {
|
||||
@@ -1152,15 +1033,10 @@ func (adapter *MegaRaidAdaptor) RemoveLogicVolumes() error {
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliClearJBODDisks() error {
|
||||
errs := make([]error, 0)
|
||||
for _, dev := range adapter.devs {
|
||||
cmd := GetCommand2(fmt.Sprintf("/c%d/e%d/s%d", adapter.index, dev.enclosure, dev.slot), "set", "good", "force")
|
||||
if _, err := adapter.remoteRun(cmd); err != nil {
|
||||
err = errors.Wrapf(err, "Set PD good storcli cmd %v", cmd)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errors.NewAggregate(errs)
|
||||
return storcliClearJBODDisks(
|
||||
adapter.GetStorcliCommand, adapter.getTerm(),
|
||||
adapter.devs,
|
||||
)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliClearJBODDisks() error {
|
||||
@@ -1263,7 +1139,7 @@ func (raid *MegaRaid) parsePhyDevsUseStorcli() error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "NewMegaRaidAdaptorByStorcli")
|
||||
}
|
||||
devs, err := ada.getMegaPhyDevs(raid)
|
||||
devs, err := ada.getMegaPhyDevs(GetCommand2, raid.term)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get storcli %d mega PDs", ada.Controller)
|
||||
}
|
||||
@@ -1364,7 +1240,3 @@ func (raid *MegaRaid) RemoveLogicVolumes() {
|
||||
adapter.RemoveLogicVolumes()
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
raiddrivers.RegisterDriver(baremetal.DISK_DRIVER_MEGARAID, NewMegaRaid)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
// 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"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
)
|
||||
|
||||
var (
|
||||
_ iDriver = new(perccliDriver)
|
||||
)
|
||||
|
||||
type perccliDriver struct{}
|
||||
|
||||
func newPerccliDriver() iDriver {
|
||||
return new(perccliDriver)
|
||||
}
|
||||
|
||||
func (_ *perccliDriver) GetName() string {
|
||||
return "MegaRAID_Perccli"
|
||||
}
|
||||
|
||||
func (_ *perccliDriver) GetAdapterConstructCmd() string {
|
||||
return getPerccliCmd("/call", "show", "|", "grep", "-iE", `'^(Controller|Product Name|Serial Number|Bus Number|Device Number|Function Number)\s='`)
|
||||
}
|
||||
|
||||
func (_ *perccliDriver) NewAdaptor(term raid.IExecTerm) iAdaptor {
|
||||
return newPerccliAdaptor(term)
|
||||
}
|
||||
|
||||
func (_ *perccliDriver) ClearForeignState(term raid.IExecTerm) error {
|
||||
cmd := getPerccliCmd("/call/fall", "delete")
|
||||
if _, err := term.Run(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPerccliCmd(args ...string) string {
|
||||
bin := "/opt/MegaRAID/perccli/perccli"
|
||||
return raid.GetCommand(bin, args...)
|
||||
}
|
||||
|
||||
type PerccliAdaptor struct {
|
||||
*StorcliAdaptor
|
||||
term raid.IExecTerm
|
||||
}
|
||||
|
||||
func newPerccliAdaptor(term raid.IExecTerm) *PerccliAdaptor {
|
||||
return &PerccliAdaptor{
|
||||
StorcliAdaptor: newStorcliAdaptor(),
|
||||
term: term,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) ParseLine(line string) {
|
||||
a.StorcliAdaptor.parseLine(line)
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) IsComplete() bool {
|
||||
return a.isComplete()
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) Key() string {
|
||||
return a.key()
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) GetPhyDevs() ([]*MegaRaidPhyDev, error) {
|
||||
return a.getMegaPhyDevs(a.getCmd, a.term)
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) ClearJBODDisks(devs []*MegaRaidPhyDev) {
|
||||
storcliClearJBODDisks(a.getAdaptorCmd, a.term, devs)
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) GetIndex() int {
|
||||
return a.Controller
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) getCmd(args ...string) string {
|
||||
return getPerccliCmd(args...)
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) getAdaptorCmd(args ...string) (string, error) {
|
||||
nargs := []string{fmt.Sprintf("/c%d", a.GetIndex())}
|
||||
nargs = append(nargs, args...)
|
||||
return a.getCmd(nargs...), nil
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) GetLogicVolumes() ([]*raid.RaidLogicalVolume, error) {
|
||||
cmd := a.getCmd(fmt.Sprintf("/c%d/vall", a.GetIndex()), "show")
|
||||
ret, err := a.term.Run(cmd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Get perccli logical volumes")
|
||||
}
|
||||
return parseStorcliLogicalVolumes(a.GetIndex(), ret)
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) RemoveLogicVolumes() error {
|
||||
lvIdx, err := a.GetLogicVolumes()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetLogicVolumes")
|
||||
}
|
||||
for _, i := range raid.ReverseLogicalArray(lvIdx) {
|
||||
cmd := a.getCmd(fmt.Sprintf("/c%d/v%d", a.GetIndex(), i.Index), "delete", "force")
|
||||
if _, err := a.term.Run(cmd); err != nil {
|
||||
return errors.Wrapf(err, "remove adaptor %d lv %d", a.GetIndex(), i.Index)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, func(bs []*baremetal.BaremetalStorage, bdc *compute.BaremetalDiskConfig) error {
|
||||
return storcliBuildRaid(a.getAdaptorCmd, a.term, devs, conf, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, func(bs []*baremetal.BaremetalStorage, bdc *compute.BaremetalDiskConfig) error {
|
||||
return storcliBuildRaid(a.getAdaptorCmd, a.term, devs, conf, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, func(bs []*baremetal.BaremetalStorage, bdc *compute.BaremetalDiskConfig) error {
|
||||
return storcliBuildRaid(a.getAdaptorCmd, a.term, devs, conf, 5)
|
||||
})
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *compute.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, func(bs []*baremetal.BaremetalStorage, bdc *compute.BaremetalDiskConfig) error {
|
||||
return storcliBuildRaid(a.getAdaptorCmd, a.term, devs, conf, 10)
|
||||
})
|
||||
}
|
||||
|
||||
func (a *PerccliAdaptor) BuildNoneRaid(devs []*baremetal.BaremetalStorage) error {
|
||||
return cliBuildRaid(devs, nil, func(bs []*baremetal.BaremetalStorage, bdc *compute.BaremetalDiskConfig) error {
|
||||
return storcliBuildNoRaid(a.getAdaptorCmd, a.term, devs)
|
||||
})
|
||||
}
|
||||
|
||||
type PerccliPhyDev struct {
|
||||
*StorcliPhysicalDrive
|
||||
}
|
||||
|
||||
func NewPerccliPhyDev(base *StorcliPhysicalDrive) *PerccliPhyDev {
|
||||
return &PerccliPhyDev{
|
||||
StorcliPhysicalDrive: base,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user