mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-07-03 11:54:34 +08:00
656 lines
17 KiB
Go
656 lines
17 KiB
Go
// 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 adaptec
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/tristate"
|
|
"yunion.io/x/pkg/util/stringutils"
|
|
|
|
api "yunion.io/x/onecloud/pkg/apis/compute"
|
|
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
|
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
|
"yunion.io/x/onecloud/pkg/util/regutils2"
|
|
)
|
|
|
|
func init() {
|
|
raid.RegisterDriver(api.DISK_DRIVER_ADAPTECRAID, NewAdaptecRaid)
|
|
}
|
|
|
|
const (
|
|
ControllerModeRaidExposeRaw = "RAID (Expose RAW)"
|
|
ControllerModeRaidHideRaw = "RAID (Hide RAW)"
|
|
ControllerModeMixed = "Mixed"
|
|
)
|
|
|
|
type AdaptecRaid struct {
|
|
term raid.IExecTerm
|
|
adapters []*AdaptecRaidAdaptor
|
|
}
|
|
|
|
func NewAdaptecRaid(term raid.IExecTerm) raid.IRaidDriver {
|
|
return &AdaptecRaid{
|
|
term: term,
|
|
adapters: make([]*AdaptecRaidAdaptor, 0),
|
|
}
|
|
}
|
|
|
|
func GetCommand(args ...string) string {
|
|
bin := "/opt/adaptec/arcconf"
|
|
return raid.GetCommand(bin, args...)
|
|
}
|
|
|
|
func (r *AdaptecRaid) GetName() string {
|
|
return baremetal.DISK_DRIVER_ADAPTECRAID
|
|
}
|
|
|
|
func (r *AdaptecRaid) ParsePhyDevs() error {
|
|
cmd := GetCommand("LIST")
|
|
ret, err := r.term.Run(cmd)
|
|
if err != nil {
|
|
return errors.Wrap(err, "list controllers")
|
|
}
|
|
if err := r.parsePhyDevs(ret); err != nil {
|
|
return errors.Wrap(err, "parse physical device")
|
|
}
|
|
if len(r.adapters) == 0 {
|
|
return errors.Errorf("Not found adaptec raid controller")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *AdaptecRaid) CleanRaid() error {
|
|
for _, ada := range r.adapters {
|
|
ada.removeJBODDisks()
|
|
ada.RemoveLogicVolumes()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *AdaptecRaid) GetAdapters() []raid.IRaidAdapter {
|
|
ret := make([]raid.IRaidAdapter, 0)
|
|
for _, a := range r.adapters {
|
|
ret = append(ret, a)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (r *AdaptecRaid) PreBuildRaid(confs []*api.BaremetalDiskConfig, adapterIdx int) error {
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
adaptorIDPatter = regexp.MustCompile(`Controller (?P<idx>[0-9]+):`)
|
|
)
|
|
|
|
func getAdaptorIndex(line string) int {
|
|
adapStr := regutils2.GetParams(adaptorIDPatter, line)["idx"]
|
|
if adapStr == "" {
|
|
return -1
|
|
}
|
|
adapInt, err := strconv.Atoi(adapStr)
|
|
if err != nil {
|
|
log.Errorf("Parse adapator string %q id error: %v", line, err)
|
|
return -1
|
|
}
|
|
return adapInt
|
|
}
|
|
|
|
func (r *AdaptecRaid) parsePhyDevs(lines []string) error {
|
|
for _, line := range lines {
|
|
index := getAdaptorIndex(line)
|
|
if index == -1 {
|
|
continue
|
|
}
|
|
ada, err := NewAdaptecRaidAdaptor(index, r)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "New raid adaptor %d", index)
|
|
}
|
|
r.adapters = append(r.adapters, ada)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type AdaptecRaidAdaptor struct {
|
|
*adaptorInfo
|
|
|
|
index int
|
|
raid *AdaptecRaid
|
|
devs []*AdaptecRaidPhyDev
|
|
}
|
|
|
|
var (
|
|
_ raid.IRaidAdapter = new(AdaptecRaidAdaptor)
|
|
)
|
|
|
|
func NewAdaptecRaidAdaptor(index int, raid *AdaptecRaid) (*AdaptecRaidAdaptor, error) {
|
|
adaptor := AdaptecRaidAdaptor{
|
|
index: index,
|
|
raid: raid,
|
|
}
|
|
if err := adaptor.fillInfo(); err != nil {
|
|
return nil, errors.Wrapf(err, "fill adaptor %d info", adaptor.index)
|
|
}
|
|
if err := adaptor.fillDevices(); err != nil {
|
|
return nil, errors.Wrap(err, "fill physical devices")
|
|
}
|
|
/*
|
|
* if !adaptor.isRaidHideRawMode() {
|
|
* if err := adaptor.setControllerModeRaidHideRaw(); err != nil {
|
|
* return nil, errors.Wrap(err, "set controller mode to raid hide raw")
|
|
* }
|
|
* }
|
|
*/
|
|
return &adaptor, nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) GetIndex() int {
|
|
return ada.index
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
|
|
if !ada.isRaidHideRawMode() {
|
|
if err := ada.setControllerModeRaidHideRaw(); err != nil {
|
|
return errors.Wrapf(err, "set controller mode to raid hide raw mode")
|
|
}
|
|
}
|
|
if err := ada.removeJBODDisks(); err != nil {
|
|
log.Warningf("remove all JBOD disks: %v", err)
|
|
}
|
|
// uninitialize all device to ready state
|
|
if err := ada.uninitializeAllDevice(); err != nil {
|
|
// return errors.Wrap(err, "uninitialize all devices")
|
|
log.Warningf("uninitializeAllDevice error: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) getInitializeCmd(args ...string) string {
|
|
newArgs := []string{"TASK", "START", fmt.Sprintf("%d", ada.GetIndex()), "DEVICE"}
|
|
newArgs = append(newArgs, args...)
|
|
newArgs = append(newArgs, "INITIALIZE", "noprompt")
|
|
return GetCommand(newArgs...)
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) initializeDevice(channel string, id string) error {
|
|
cmd := ada.getInitializeCmd(channel, id)
|
|
_, err := ada.remoteRun(fmt.Sprintf("initialize device %s:%s", channel, id), cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) initializeAllDevice() error {
|
|
cmd := ada.getInitializeCmd("ALL")
|
|
_, err := ada.remoteRun("initialize all device", cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) uninitializeDevice(channel string, id string) error {
|
|
cmd := ada.getUninitializeCmd(channel, id)
|
|
_, err := ada.remoteRun(fmt.Sprintf("uninitialize device %s:%s", channel, id), cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) getUninitializeCmd(args ...string) string {
|
|
newArgs := []string{"TASK", "START", fmt.Sprintf("%d", ada.GetIndex()), "DEVICE"}
|
|
newArgs = append(newArgs, args...)
|
|
newArgs = append(newArgs, "UNINITIALIZE", "noprompt")
|
|
return GetCommand(newArgs...)
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) uninitializeAllDevice() error {
|
|
cmd := ada.getUninitializeCmd("ALL")
|
|
_, err := ada.remoteRun("uninitialize all devices", cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) getTerm() raid.IExecTerm {
|
|
return ada.raid.term
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) remoteRun(hint string, cmd string) ([]string, error) {
|
|
out, err := ada.getTerm().Run(cmd)
|
|
if err != nil {
|
|
return out, errors.Wrapf(err, "%q, out: %v", hint, out)
|
|
}
|
|
log.Debugf("remote run cmd %s %q successfully: %v", hint, cmd, out)
|
|
return out, nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) fillInfo() error {
|
|
cmd := GetCommand("GETCONFIG", fmt.Sprintf("%d", ada.index), "AD")
|
|
ret, err := ada.remoteRun("get AD config", cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
info, err := getAdaptorInfo(ret)
|
|
if err != nil {
|
|
return errors.Wrap(err, "get adaptor info")
|
|
}
|
|
ada.adaptorInfo = info
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) fillDevices() error {
|
|
cmd := GetCommand("GETCONFIG", fmt.Sprintf("%d", ada.index), "PD")
|
|
ret, err := ada.remoteRun("get PD config", cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
devs := getPhyDevices(ada.GetIndex(), ret)
|
|
ada.devs = append(ada.devs, devs...)
|
|
return nil
|
|
}
|
|
|
|
func getPhyDevices(adapter int, lines []string) []*AdaptecRaidPhyDev {
|
|
dev := newPhyDev(adapter)
|
|
devs := make([]*AdaptecRaidPhyDev, 0)
|
|
for _, line := range lines {
|
|
if dev.parseLine(line) && dev.isComplete() {
|
|
tmpDev := dev
|
|
devs = append(devs, tmpDev)
|
|
dev = newPhyDev(adapter)
|
|
}
|
|
}
|
|
return devs
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) getChannelId(storage *baremetal.BaremetalStorage) (string, string, error) {
|
|
if storage.Addr == "" {
|
|
return "", "", errors.Errorf("storage %#v addr is empty", storage)
|
|
}
|
|
parts := strings.Split(storage.Addr, ":")
|
|
if len(parts) != 2 {
|
|
return "", "", errors.Errorf("invalid storage %#v addr %q", storage, storage.Addr)
|
|
}
|
|
return parts[0], parts[1], nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) getCreateCmd(args ...string) string {
|
|
newArgs := []string{"CREATE", fmt.Sprintf("%d", ada.GetIndex())}
|
|
newArgs = append(newArgs, args...)
|
|
return GetCommand(newArgs...)
|
|
}
|
|
|
|
// setControllerMode change adapter controller's mode
|
|
// Controller Modes : 0 - RAID: Expose RAW
|
|
// : 1 - Auto Volume Mode
|
|
// : 2 - HBA Mode
|
|
// : 3 - RAID: Hide RAW
|
|
// : 4 - Simple Volume Mode
|
|
// : 5 - Mixed
|
|
func (ada *AdaptecRaidAdaptor) setControllerMode(mode int) error {
|
|
cmd := GetCommand("SETCONTROLLERMODE", fmt.Sprintf("%d", ada.GetIndex()), fmt.Sprintf("%d", mode), "noprompt")
|
|
if _, err := ada.remoteRun(fmt.Sprintf("set controller mode to %d", mode), cmd); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) setControllerModeRaidExposeRaw() error {
|
|
if err := ada.setControllerMode(0); err != nil {
|
|
return errors.Wrap(err, "mode raid expose raw")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) setControllerModeRaidHideRaw() error {
|
|
if err := ada.setControllerMode(3); err != nil {
|
|
return errors.Wrap(err, "mode raid hide raw")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) setControllerModeMixed() error {
|
|
if err := ada.setControllerMode(5); err != nil {
|
|
return errors.Wrap(err, "mode mixed")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) buildJBOD(dev *baremetal.BaremetalStorage) error {
|
|
channel, id, err := ada.getChannelId(dev)
|
|
if err != nil {
|
|
return errors.Wrap(err, "get channel and id")
|
|
}
|
|
cmd := ada.getCreateCmd("JBOD", channel, id, "noprompt")
|
|
if out, err := ada.remoteRun("create JBOD", cmd); err != nil {
|
|
return errors.Wrapf(err, "run cmd %q, out: %q", cmd, out)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) buildNonRaid(dev *baremetal.BaremetalStorage) error {
|
|
// set to raid expose raw mode or mixed mode
|
|
if !ada.isRaidExposeRawMode() && !ada.isMixedMode() {
|
|
err := func() error {
|
|
errs := []error{}
|
|
if err := ada.setControllerModeRaidExposeRaw(); err != nil {
|
|
errs = append(errs, err)
|
|
} else {
|
|
return nil
|
|
}
|
|
if err := ada.setControllerModeMixed(); err != nil {
|
|
errs = append(errs, err)
|
|
} else {
|
|
return nil
|
|
}
|
|
return errors.NewAggregate(errs)
|
|
}()
|
|
if err != nil {
|
|
return errors.Wrap(err, "set raid to expose raw or mixed mode")
|
|
}
|
|
}
|
|
// try build JBOD firstly
|
|
if err := ada.buildJBOD(dev); err != nil {
|
|
log.Warningf("try build JBOD error: %v", err)
|
|
} else {
|
|
return nil
|
|
}
|
|
// just uninitialize device when build JBOD fail
|
|
channel, id, err := ada.getChannelId(dev)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := ada.uninitializeDevice(channel, id); err != nil {
|
|
return errors.Wrapf(err, "uninitialize device %v when build jbod fail", dev)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) BuildNoneRaid(devs []*baremetal.BaremetalStorage) error {
|
|
for _, dev := range devs {
|
|
if err := ada.buildNonRaid(dev); err != nil {
|
|
return errors.Wrap(err, "build nonraid")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) getBuildRaidCmd(level int, devs []*baremetal.BaremetalStorage) (string, error) {
|
|
if len(devs) == 0 {
|
|
return "", errors.Errorf("devices is empty")
|
|
}
|
|
args := []string{"LOGICALDRIVE", "MAX", fmt.Sprintf("%d", level)}
|
|
chIds := []string{}
|
|
for _, dev := range devs {
|
|
ch, id, err := ada.getChannelId(dev)
|
|
if err != nil {
|
|
return "", errors.Wrapf(err, "get device %v channel id", dev)
|
|
}
|
|
chIds = append(chIds, ch, id)
|
|
}
|
|
args = append(args, chIds...)
|
|
cmd := ada.getCreateCmd(args...)
|
|
return cmd, nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) buildRaid(level int, devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
|
// initialize each devs
|
|
for _, dev := range devs {
|
|
channel, id, err := ada.getChannelId(dev)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "get device %v channel id", dev)
|
|
}
|
|
if err := ada.initializeDevice(channel, id); err != nil {
|
|
// return errors.Wrapf(err, "initialize device")
|
|
log.Warningf("initialize device error: %v", err)
|
|
}
|
|
}
|
|
|
|
// TODO: support config to build raid params
|
|
cmd, err := ada.getBuildRaidCmd(level, devs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = ada.remoteRun(fmt.Sprintf("build raid %d", level), cmd)
|
|
return err
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
|
return ada.buildRaid(0, devs, conf)
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
|
return ada.buildRaid(1, devs, conf)
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
|
return ada.buildRaid(5, devs, conf)
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
|
return ada.buildRaid(10, devs, conf)
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) GetDevices() []*baremetal.BaremetalStorage {
|
|
ret := []*baremetal.BaremetalStorage{}
|
|
for idx, dev := range ada.devs {
|
|
ret = append(ret, dev.ToBaremetalStorage(idx))
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) GetLogicVolumes() ([]*raid.RaidLogicalVolume, error) {
|
|
cmd := GetCommand("GETCONFIG", fmt.Sprintf("%d", ada.index), "LD")
|
|
ret, err := ada.remoteRun("get logic volumes", cmd)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Get logic volumes error: %v", err)
|
|
}
|
|
return getLogicalVolumes(ada.index, ret)
|
|
}
|
|
|
|
func getLogicalVolumes(adapter int, lines []string) ([]*raid.RaidLogicalVolume, error) {
|
|
lvs := make([]*raid.RaidLogicalVolume, 0)
|
|
for _, line := range lines {
|
|
m := regutils2.SubGroupMatch(`Logical Device number\s+(?P<idx>\d+)`, line)
|
|
if len(m) > 0 {
|
|
idxStr := m["idx"]
|
|
idx, err := strconv.Atoi(idxStr)
|
|
if err != nil {
|
|
return nil, errors.Errorf("%s index str is not digit: %v", idxStr, err)
|
|
}
|
|
lvs = append(lvs, &raid.RaidLogicalVolume{
|
|
Index: idx,
|
|
Adapter: adapter,
|
|
})
|
|
}
|
|
}
|
|
return lvs, nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) removeJBODDisks() error {
|
|
cmd := GetCommand("DELETE", fmt.Sprintf("%d", ada.index), "JBOD", "ALL", "noprompt")
|
|
out, err := ada.remoteRun("delete JBOD disks", cmd)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "delete all JBOD output: %q", out)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ada *AdaptecRaidAdaptor) RemoveLogicVolumes() error {
|
|
lvs, err := ada.GetLogicVolumes()
|
|
if err != nil {
|
|
return errors.Wrap(err, "get logic volumes")
|
|
}
|
|
if len(lvs) == 0 {
|
|
return nil
|
|
}
|
|
cmd := GetCommand("DELETE", fmt.Sprintf("%d", ada.index), "LOGICALDRIVE", "ALL", "noprompt")
|
|
out, err := ada.remoteRun("delete logical volumes", cmd)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "delete all logicaldrive output: %q", out)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type adaptorInfo struct {
|
|
status string
|
|
mode string
|
|
name string
|
|
sn string
|
|
wwn string
|
|
slot string
|
|
}
|
|
|
|
func (ada *adaptorInfo) key() string {
|
|
return ada.name + ada.sn
|
|
}
|
|
|
|
func (ada *adaptorInfo) isRaidExposeRawMode() bool {
|
|
return ada.mode == ControllerModeRaidExposeRaw
|
|
}
|
|
|
|
func (ada *adaptorInfo) isRaidHideRawMode() bool {
|
|
return ada.mode == ControllerModeRaidHideRaw
|
|
}
|
|
|
|
func (ada *adaptorInfo) isMixedMode() bool {
|
|
return ada.mode == ControllerModeMixed
|
|
}
|
|
|
|
func getAdaptorInfo(lines []string) (*adaptorInfo, error) {
|
|
ada := new(adaptorInfo)
|
|
for _, l := range lines {
|
|
key, val := stringutils.SplitKeyValue(l)
|
|
if len(key) == 0 {
|
|
continue
|
|
}
|
|
switch key {
|
|
case "Controller Status":
|
|
ada.status = val
|
|
case "Controller Mode":
|
|
ada.mode = val
|
|
case "Controller Model":
|
|
ada.name = val
|
|
case "Controller Serial Number":
|
|
ada.sn = val
|
|
case "Controller World Wide Name":
|
|
ada.wwn = val
|
|
case "Physical Slot":
|
|
ada.slot = val
|
|
}
|
|
}
|
|
if len(ada.key()) == 0 {
|
|
return nil, errors.Errorf("Not found SN and model name")
|
|
}
|
|
return ada, nil
|
|
}
|
|
|
|
type AdaptecRaidPhyDev struct {
|
|
*raid.RaidBasePhyDev
|
|
// channelId and deviceId is parsed by Reported Channel,Device(T:L)
|
|
// e.g.: Reported Channel,Device(T:L) : 0,6(6:0)
|
|
channelId string
|
|
deviceId string
|
|
}
|
|
|
|
func newPhyDev(adapter int) *AdaptecRaidPhyDev {
|
|
dev := &AdaptecRaidPhyDev{
|
|
RaidBasePhyDev: raid.NewRaidBasePhyDev(api.DISK_DRIVER_ADAPTECRAID),
|
|
}
|
|
dev.Adapter = adapter
|
|
return dev
|
|
}
|
|
|
|
func (dev *AdaptecRaidPhyDev) isComplete() bool {
|
|
if !dev.RaidBasePhyDev.IsComplete() {
|
|
return false
|
|
}
|
|
if dev.channelId == "" || dev.deviceId == "" {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (dev *AdaptecRaidPhyDev) ToBaremetalStorage(index int) *baremetal.BaremetalStorage {
|
|
s := dev.RaidBasePhyDev.ToBaremetalStorage(index)
|
|
s.Addr = fmt.Sprintf("%s:%s", dev.channelId, dev.deviceId)
|
|
|
|
return s
|
|
}
|
|
|
|
var (
|
|
channelDeviceRegexp = regexp.MustCompile(`Reported Channel,Device\(T:L\).*(?P<channel>\d+),(?P<device>\d+)\(\d+:\d+\)`)
|
|
)
|
|
|
|
func (dev *AdaptecRaidPhyDev) parseLine(line string) bool {
|
|
chanDevMatch := regutils2.GetParams(channelDeviceRegexp, line)
|
|
if len(chanDevMatch) != 0 {
|
|
channelId := chanDevMatch["channel"]
|
|
deviceId := chanDevMatch["device"]
|
|
dev.channelId = channelId
|
|
dev.deviceId = deviceId
|
|
return true
|
|
}
|
|
key, val := stringutils.SplitKeyValue(line)
|
|
if key == "" {
|
|
return false
|
|
}
|
|
switch key {
|
|
case "Total Size":
|
|
dat := strings.Split(val, " ")
|
|
szStr, unitStr := dat[0], dat[1]
|
|
var sz int64
|
|
szInt, err := strconv.Atoi(szStr)
|
|
if err != nil {
|
|
log.Errorf("Parse size string %s: %v", szStr, err)
|
|
return false
|
|
}
|
|
switch unitStr {
|
|
case "GB":
|
|
sz = int64(szInt * 1000 * 1000 * 100)
|
|
case "TB":
|
|
sz = int64(szInt * 1000 * 1000 * 1000 * 1000)
|
|
case "MB":
|
|
sz = int64(szInt * 1000 * 1000)
|
|
default:
|
|
log.Errorf("Unsupported unit: %s", unitStr)
|
|
return false
|
|
}
|
|
dev.Size = sz / 1024 / 1024
|
|
case "Model":
|
|
dev.Model = strings.Join(regexp.MustCompile(`\s+`).Split(val, -1), " ")
|
|
case "State":
|
|
dev.Status = val
|
|
case "SSD":
|
|
if val == "No" {
|
|
dev.Rotate = tristate.True
|
|
} else {
|
|
dev.Rotate = tristate.False
|
|
}
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
}
|