| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733 |
- // 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 baremetal
- import (
- "encoding/json"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/sets"
- "yunion.io/x/pkg/utils"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
- )
- func ParseDiskConfig(desc string) (api.BaremetalDiskConfig, error) {
- conf, err := cmdline.ParseBaremetalDiskConfig(desc)
- if err != nil {
- return api.BaremetalDiskConfig{}, err
- }
- return *conf, nil
- }
- func isDiskConfigStorageMatch(
- config *api.BaremetalDiskConfig,
- confDriver *string,
- confAdapter *int,
- storage *BaremetalStorage,
- selected []*BaremetalStorage,
- ) (bool, error) {
- isRotate := storage.Rotate
- adapter := storage.Adapter
- index := storage.Index
- driver := storage.Driver
- typeIsHybrid := config.Type == DISK_TYPE_HYBRID
- typeIsRotate := config.Type == DISK_TYPE_ROTATE && isRotate
- typeIsSSD := config.Type == DISK_TYPE_SSD && !isRotate
- rangeIsNoneAndCountZero := len(config.Range) == 0 && config.Count == 0
- rangeIsNotNoneAndIndexInRange := len(config.Range) != 0 && sets.NewInt64(config.Range...).Has(index)
- rangeIsNoneAndSmallThanCount := len(config.Range) == 0 && int64(len(selected)) < config.Count
- adapterIsEqual := (confAdapter == nil || *confAdapter == adapter) &&
- (confDriver == nil || *confDriver == driver)
- if (typeIsHybrid || typeIsRotate || typeIsSSD) &&
- (rangeIsNoneAndCountZero || rangeIsNotNoneAndIndexInRange || rangeIsNoneAndSmallThanCount) &&
- adapterIsEqual {
- return true, nil
- }
- errs := []error{}
- // aggregate errors
- if !(typeIsHybrid || typeIsRotate || typeIsSSD) {
- errs = append(errs, fmt.Errorf("check type: is_hybrid: %v, is_rotate: %v, is_ssd: %v, type: %s", typeIsHybrid, typeIsRotate, typeIsSSD, config.Type))
- }
- if !(rangeIsNoneAndCountZero || rangeIsNotNoneAndIndexInRange || rangeIsNoneAndSmallThanCount) {
- errs = append(errs, fmt.Errorf("check range: is_none: %v, index_in_range: %v, small_than_count: %v, index: %d, range: %v", rangeIsNoneAndCountZero, rangeIsNotNoneAndIndexInRange, rangeIsNoneAndSmallThanCount, index, config.Range))
- }
- if adapterIsEqual {
- errs = append(errs, fmt.Errorf("check adapter: is_equal: %v", adapterIsEqual))
- }
- return false, errors.NewAggregate(errs)
- }
- func RetrieveStorages(diskConfig *api.BaremetalDiskConfig, storages []*BaremetalStorage) (selected, rest []*BaremetalStorage, err error) {
- var confDriver *string = nil
- var confAdapter *int = nil
- if diskConfig.Adapter != nil {
- confAdapter = diskConfig.Adapter
- }
- if diskConfig.Driver != "" {
- confDriver = &diskConfig.Driver
- }
- selected = make([]*BaremetalStorage, 0)
- rest = make([]*BaremetalStorage, 0)
- errs := []error{}
- idx := 0
- curAdapter := 0
- adapterChange := false
- curDriver := ""
- driverChange := false
- for _, storage := range storages {
- if storage.Adapter != curAdapter {
- adapterChange = true
- curAdapter = storage.Adapter
- }
- if storage.Driver != curDriver {
- driverChange = true
- curDriver = storage.Driver
- }
- if adapterChange {
- idx = 0
- adapterChange = false
- }
- if driverChange {
- idx = 0
- driverChange = false
- }
- if storage.Index == 0 {
- storage.Index = int64(idx)
- }
- if isMatched, mErr := isDiskConfigStorageMatch(diskConfig, confDriver, confAdapter, storage, selected); isMatched {
- if confDriver == nil {
- confDriver = &storage.Driver
- }
- if confAdapter == nil {
- confAdapter = &storage.Adapter
- }
- selected = append(selected, storage)
- } else {
- rest = append(rest, storage)
- errs = append(errs, mErr)
- }
- if confDriver == nil {
- idx++
- } else if *confDriver == storage.Driver {
- idx++
- }
- }
- if len(errs) > 0 {
- err = errors.NewAggregate(errs)
- }
- return
- }
- func GetMinDiskRequirement(diskConfig string) int {
- minDisk := 1
- if diskConfig == DISK_CONF_RAID1 {
- minDisk = 2
- }
- if diskConfig == DISK_CONF_RAID5 {
- minDisk = 3
- } else if diskConfig == DISK_CONF_RAID10 {
- minDisk = 4
- }
- return minDisk
- }
- func RequireEvenDisks(diskConfig string) bool {
- if sets.NewString(
- DISK_CONF_RAID10,
- DISK_CONF_RAID1,
- ).Has(diskConfig) {
- return true
- }
- return false
- }
- type Layout struct {
- Disks []*BaremetalStorage `json:"disks"`
- Conf *api.BaremetalDiskConfig `json:"conf"`
- Size int64 `json:"size"`
- }
- func (l Layout) String() string {
- bytes, _ := json.MarshalIndent(l, "", " ")
- return string(bytes)
- }
- func RetrieveStorageDrivers(storages []*BaremetalStorage) sets.String {
- ret := sets.NewString()
- for _, s := range storages {
- if !ret.Has(s.Driver) {
- ret.Insert(s.Driver)
- }
- }
- return ret
- }
- func MeetConfig(
- conf *api.BaremetalDiskConfig,
- storages []*BaremetalStorage,
- ) error {
- storageDrvs := RetrieveStorageDrivers(storages)
- if len(storageDrvs.List()) > 1 {
- return fmt.Errorf("%v more than 1 storages drivers", storageDrvs)
- }
- driver := storageDrvs.List()[0]
- //if conf.Conf != DISK_CONF_NONE && !DISK_DRIVERS_RAID.Has(driver) {
- // return fmt.Errorf("BaremetalStorage driver %s not support RAID", driver)
- //}
- minDisk := GetMinDiskRequirement(conf.Conf)
- if len(storages) < minDisk {
- return fmt.Errorf("%q requires at least %d disks", conf.Conf, minDisk)
- }
- if RequireEvenDisks(conf.Conf) && (len(storages)%2) != 0 {
- return fmt.Errorf("%q requires event number of disks", conf.Conf)
- }
- if len(conf.Splits) > 0 &&
- sets.NewString(
- DISK_CONF_NONE,
- DISK_DRIVER_MPT2SAS).Has(conf.Conf) {
- return fmt.Errorf("Cannot divide a normal disk into splits")
- }
- if driver == DISK_DRIVER_MPT2SAS {
- if conf.Conf == DISK_CONF_RAID5 {
- return fmt.Errorf("%q not support RAID5", DISK_DRIVER_MPT2SAS)
- }
- if conf.Conf == DISK_CONF_RAID0 && len(storages) < 2 {
- return fmt.Errorf("%q %q requires at least 2 disks", DISK_DRIVER_MPT2SAS, DISK_CONF_RAID0)
- }
- if conf.Conf == DISK_CONF_RAID10 && len(storages) > 10 {
- return fmt.Errorf("%q %q only support no more than 10 disks", DISK_DRIVER_MPT2SAS, DISK_CONF_RAID10)
- }
- }
- if driver == DISK_DRIVER_MEGARAID && conf.Strip != nil {
- minStripSize := storages[0].MinStripSize
- maxStripSize := storages[0].MaxStripSize
- if maxStripSize != -1 && minStripSize != -1 {
- size := *conf.Strip
- if size > maxStripSize || size < minStripSize {
- return fmt.Errorf("%q input strip size out of range(%d, %d), input: %d", DISK_DRIVER_MEGARAID, minStripSize, maxStripSize, size)
- }
- }
- }
- return nil
- }
- func GetStoragesMinSize(ss []*BaremetalStorage) int64 {
- minSize := int64(-1)
- for _, s := range ss {
- if minSize < 0 || minSize > s.Size {
- minSize = s.Size
- }
- }
- return minSize
- }
- func CalculateSize(conf string, storages []*BaremetalStorage) int64 {
- if conf == "" {
- conf = DEFAULT_DISK_CONF
- }
- var size int64
- if conf == DISK_CONF_RAID5 {
- size = GetStoragesMinSize(storages) * int64(len(storages)-1)
- } else if sets.NewString(DISK_CONF_RAID10, DISK_CONF_RAID1).Has(conf) {
- size = GetStoragesMinSize(storages) * int64((len(storages) / 2))
- } else {
- for _, s := range storages {
- size += s.Size
- }
- }
- return size
- }
- func GetSplitSizes(size int64, splitConf string) []int64 {
- ssizes := strings.Split(splitConf, ",")
- isizes := make([]int64, len(ssizes))
- leftoverIdx := -1
- subtotal := int64(0)
- for index := range ssizes {
- if strings.HasSuffix(ssizes[index], "%") {
- ssizeFloat64, err := strconv.ParseFloat(ssizes[index][:len(ssizes[index])-1], 64)
- if err != nil {
- log.Errorf("GetSplitSizes ParseFloat err: %v", err)
- continue
- }
- isizes[index] = int64(ssizeFloat64 / float64(100) * float64(size))
- subtotal += isizes[index]
- } else if ssizes[index] != "" {
- isizes[index], _ = utils.GetSizeMB(ssizes[index], "M")
- subtotal += isizes[index]
- } else {
- if leftoverIdx >= 0 {
- log.Errorf("%v", ErrMoreThanOneSizeUnspecificSplit)
- return []int64{}
- }
- leftoverIdx = index
- }
- }
- if leftoverIdx >= 0 {
- isizes[leftoverIdx] = size - subtotal
- if isizes[leftoverIdx] <= 0 {
- log.Errorf("%v", ErrNoMoreSpaceForUnspecificSplit)
- return []int64{}
- }
- } else {
- if subtotal > size {
- log.Errorf("%v", ErrSubtotalOfSplitExceedsDiskSize)
- return []int64{}
- }
- }
- return isizes
- }
- func ExpandNoneConf(layouts []Layout) (ret []Layout) {
- for _, layout := range layouts {
- if layout.Conf.Conf == DISK_CONF_NONE && len(layout.Disks) >= 1 {
- conf := layout.Conf
- conf.Count = 1
- for _, disk := range layout.Disks {
- ret = append(ret, Layout{Disks: []*BaremetalStorage{disk}, Conf: conf, Size: disk.Size})
- }
- } else {
- ret = append(ret, layout)
- }
- }
- return ret
- }
- func GetLayoutRaidConfig(layouts []Layout) []*api.BaremetalDiskConfig {
- return getLayoutConfig(layouts, true)
- }
- func GetLayoutDiskConfig(layouts []Layout) []*api.BaremetalDiskConfig {
- return getLayoutConfig(layouts, false)
- }
- func getLayoutConfig(layouts []Layout, onlyRaidDisk bool) []*api.BaremetalDiskConfig {
- var disk []*BaremetalStorage
- ret := make([]*api.BaremetalDiskConfig, 0)
- for _, layout := range layouts {
- if onlyRaidDisk && layout.Conf.Conf == DISK_CONF_NONE &&
- sets.NewString(DISK_DRIVER_LINUX, DISK_DRIVER_PCIE).Has(layout.Disks[0].Driver) {
- continue
- }
- if !reflect.DeepEqual(disk, layout.Disks) {
- ret = append(ret, layout.Conf)
- disk = layout.Disks
- lastConf := ret[len(ret)-1]
- /*
- if 'size' in ret[-1]:
- ret[-1]['size'] = [ret[-1]['size']]
- */
- if lastConf.Size == nil {
- lastConf.Size = make([]int64, 0)
- }
- } else {
- lastConf := ret[len(ret)-1]
- lastConf.Size = append(lastConf.Size, layout.Conf.Size...)
- }
- }
- return ret
- }
- func CalculateLayout(confs []*api.BaremetalDiskConfig, storages []*BaremetalStorage) (layouts []Layout, err error) {
- var confIdx = 0
- var softRaidIdx = 0
- for len(storages) > 0 {
- var conf *api.BaremetalDiskConfig
- if confIdx < len(confs) {
- conf = confs[confIdx]
- confIdx += 1
- } else {
- noneConf, _ := ParseDiskConfig(DISK_CONF_NONE)
- conf = &noneConf
- }
- // is soft raid
- if DISK_DRIVERS_SOFT_RAID.Has(conf.Driver) && conf.Conf != DISK_CONF_NONE {
- idx := softRaidIdx
- conf.SoftRaidIdx = &idx
- softRaidIdx += 1
- }
- selected, restStorages, rErr := RetrieveStorages(conf, storages)
- storages = restStorages
- if len(selected) == 0 {
- err = errors.Wrapf(rErr, "not found matched storages by config: %#v", conf)
- return
- }
- resultErr := MeetConfig(conf, selected)
- if resultErr != nil {
- err = fmt.Errorf("selected storages %#v not meet baremetal dick config: %#v, err: %v", selected, conf, resultErr)
- return
- }
- sz := CalculateSize(conf.Conf, selected)
- if len(conf.Splits) == 0 {
- layouts = append(layouts, Layout{
- Disks: selected,
- Conf: conf,
- Size: sz,
- })
- } else {
- splitSizes := GetSplitSizes(sz, conf.Splits)
- conf.Size = splitSizes
- layouts = append(layouts, Layout{
- Disks: selected,
- Conf: conf,
- Size: sz,
- })
- }
- }
- if confIdx < len(confs) {
- err = fmt.Errorf("Not enough disks to meet configuration")
- }
- return
- }
- func expandLayoutSplits(layouts []Layout) []Layout {
- ret := make([]Layout, 0)
- for _, l := range layouts {
- splitSizes := GetSplitSizes(l.Size, l.Conf.Splits)
- if len(splitSizes) <= 0 {
- ret = append(ret, l)
- } else {
- for _, ssz := range splitSizes {
- subLayout := l
- subLayout.Size = ssz
- ret = append(ret, subLayout)
- }
- }
- }
- return ret
- }
- func IsDisksAllocable(layouts []Layout, disks []*api.DiskConfig) bool {
- allocable, _ := CheckDisksAllocable(layouts, disks)
- return allocable
- }
- func CheckDisksAllocable(layouts []Layout, disks []*api.DiskConfig) (bool, []*api.DiskConfig) {
- layouts = ExpandNoneConf(layouts)
- layouts = expandLayoutSplits(layouts)
- storeIndex := 0
- storeFreeSize := int64(-1)
- diskIndex := 0
- layoutLen := len(layouts)
- for _, disk := range disks {
- if storeIndex >= layoutLen {
- break
- }
- if storeFreeSize < 0 {
- storeFreeSize = layouts[storeIndex].Size - 2 // start, end space
- }
- if disk.SizeMb > 0 {
- if storeFreeSize >= int64(disk.SizeMb) {
- storeFreeSize -= int64(disk.SizeMb)
- diskIndex++
- if storeFreeSize == 0 {
- storeIndex++
- storeFreeSize = -1
- }
- } else {
- store := layouts[storeIndex]
- log.Warningf("Disk size %dMB large than storage size %dMB, skip storage %s", disk.SizeMb, storeFreeSize, jsonutils.Marshal(store).PrettyString())
- storeIndex++
- storeFreeSize = -1
- }
- } else {
- diskIndex++
- storeIndex++
- storeFreeSize = -1
- }
- }
- if diskIndex < len(disks) {
- return false, nil
- }
- extraDisks := make([]*api.DiskConfig, 0)
- for ; storeIndex < layoutLen; storeIndex += 1 {
- disk := api.DiskConfig{SizeMb: -1}
- extraDisks = append(extraDisks, &disk)
- }
- return true, extraDisks
- }
- func NewBaremetalDiskConfigs(dss ...string) ([]*api.BaremetalDiskConfig, error) {
- ret := make([]*api.BaremetalDiskConfig, 0)
- for _, ds := range dss {
- r, err := ParseDiskConfig(ds)
- if err != nil {
- return nil, err
- }
- ret = append(ret, &r)
- }
- return ret, nil
- }
- func getStorageDiskType(isRotate bool) string {
- if isRotate {
- return HDD_DISK_SPEC_TYPE
- }
- return SSD_DISK_SPEC_TYPE
- }
- func NewDiskSpec(s *BaremetalStorage, index int) *api.DiskSpec {
- return &api.DiskSpec{
- Type: getStorageDiskType(s.Rotate),
- Size: s.Size,
- StartIndex: index,
- EndIndex: index,
- Count: 1,
- }
- }
- func IsDiskSpecSameAs(ds *api.DiskSpec, s *BaremetalStorage, index int) bool {
- if ds.Size != s.Size {
- return false
- }
- dType := getStorageDiskType(s.Rotate)
- if ds.Type != dType {
- return false
- }
- // discontinuity check
- if ds.EndIndex != (index - 1) {
- return false
- }
- return true
- }
- func addDiskSpecStorage(ds *api.DiskSpec, s *BaremetalStorage, index int) {
- ds.Count++
- if s.Index != 0 {
- ds.EndIndex = index
- } else {
- ds.EndIndex++
- }
- }
- func GetDiskSpecs(storages []*BaremetalStorage) []*api.DiskSpec {
- diskSpecs := make([]*api.DiskSpec, 0)
- for idx, s := range storages {
- var lastSpec *api.DiskSpec
- if len(diskSpecs) != 0 {
- lastSpec = diskSpecs[len(diskSpecs)-1]
- }
- if lastSpec == nil || !IsDiskSpecSameAs(lastSpec, s, idx) {
- ds := NewDiskSpec(s, idx)
- diskSpecs = append(diskSpecs, ds)
- } else {
- addDiskSpecStorage(lastSpec, s, idx)
- }
- }
- return diskSpecs
- }
- func getStoragesByDriver(driver string, storages []*BaremetalStorage) []*BaremetalStorage {
- ret := make([]*BaremetalStorage, 0)
- for _, s := range storages {
- if s.Driver == driver {
- ret = append(ret, s)
- }
- }
- return ret
- }
- func groupByAdapter(storages []*BaremetalStorage) map[string][]*BaremetalStorage {
- ret := make(map[string][]*BaremetalStorage)
- for _, storage := range storages {
- adapter := storage.Adapter
- adapterKey := fmt.Sprintf("adapter%d", adapter)
- oldStorages := ret[adapterKey]
- if len(oldStorages) == 0 {
- ret[adapterKey] = []*BaremetalStorage{storage}
- } else {
- oldStorages = append(oldStorages, storage)
- ret[adapterKey] = oldStorages
- }
- }
- return ret
- }
- func getSpec(storages []*BaremetalStorage) api.DiskAdapterSpec {
- ret := make(map[string][]*api.DiskSpec)
- for adapterKey, newStorages := range groupByAdapter(storages) {
- if len(newStorages) == 0 {
- continue
- }
- ret[adapterKey] = GetDiskSpecs(newStorages)
- }
- return ret
- }
- func GetDiskSpecV2(storages []*BaremetalStorage) api.DiskDriverSpec {
- spec := make(map[string]api.DiskAdapterSpec)
- for _, driver := range DISK_DRIVERS.List() {
- driverStorages := getStoragesByDriver(driver, storages)
- if len(driverStorages) == 0 {
- continue
- }
- spec[driver] = getSpec(driverStorages)
- }
- return spec
- }
- type DiskConfiguration struct {
- Driver string
- Adapter int
- RaidConfig string
- Block int64
- Size int64
- DiskType string
- SoftRaidIdx *int
- }
- func GetDiskConfigurations(layouts []Layout) []DiskConfiguration {
- disks := make([]DiskConfiguration, 0)
- for _, rr := range layouts {
- driver := rr.Disks[0].Driver
- adapter := rr.Disks[0].Adapter
- block := rr.Disks[0].GetBlock()
- raidConf := rr.Conf.Conf
- if raidConf == DISK_CONF_NONE {
- for _, d := range rr.Disks {
- disks = append(disks, DiskConfiguration{
- Driver: driver,
- Adapter: adapter,
- RaidConfig: raidConf,
- Block: block,
- Size: d.Size,
- DiskType: rr.Conf.Type,
- SoftRaidIdx: rr.Conf.SoftRaidIdx,
- })
- }
- } else {
- if len(rr.Conf.Size) != 0 {
- for _, sz := range rr.Conf.Size {
- disks = append(disks, DiskConfiguration{
- Driver: driver,
- Adapter: adapter,
- RaidConfig: raidConf,
- Block: block,
- Size: sz,
- DiskType: rr.Conf.Type,
- SoftRaidIdx: rr.Conf.SoftRaidIdx,
- })
- }
- } else {
- disks = append(disks, DiskConfiguration{
- Driver: driver,
- Adapter: adapter,
- RaidConfig: raidConf,
- Block: block,
- Size: rr.Size,
- DiskType: rr.Conf.Type,
- SoftRaidIdx: rr.Conf.SoftRaidIdx,
- })
- }
- }
- }
- return disks
- }
- type DriverAdapterDiskConfig struct {
- Driver string
- Adapter int
- Configs []*api.BaremetalDiskConfig
- }
- func GroupLayoutResultsByDriverAdapter(layouts []Layout) []*DriverAdapterDiskConfig {
- ret := make([]*DriverAdapterDiskConfig, 0)
- tbl := make(map[string]*DriverAdapterDiskConfig)
- for _, layout := range layouts {
- driver := layout.Disks[0].Driver
- adapter := layout.Disks[0].Adapter
- key := fmt.Sprintf("%s.%d", driver, adapter)
- if item, ok := tbl[key]; ok {
- item.Configs = append(item.Configs, layout.Conf)
- } else {
- item := &DriverAdapterDiskConfig{
- Driver: driver,
- Adapter: adapter,
- Configs: []*api.BaremetalDiskConfig{layout.Conf},
- }
- ret = append(ret, item)
- tbl[key] = item
- }
- }
- return ret
- }
- func ValidateDiskConfigs(confs []*api.BaremetalDiskConfig) error {
- if len(confs) == 0 {
- return nil
- }
- for idx, conf := range confs {
- if conf.Conf != DISK_CONF_NONE {
- // raid validate
- if idx > 0 {
- preConf := confs[idx-1]
- if preConf.Conf == DISK_CONF_NONE {
- return fmt.Errorf("Raid config %d must before none raid config", idx)
- }
- }
- } else {
- // none raid validate
- if idx+1 == len(confs) {
- return nil
- }
- restConfs := confs[idx+1:]
- hasRaidConf := false
- for _, restConf := range restConfs {
- if restConf.Conf != DISK_CONF_NONE {
- hasRaidConf = true
- }
- }
- if hasRaidConf {
- return fmt.Errorf("Raid config after none raid config %d", idx)
- }
- }
- }
- return nil
- }
- func ValidateRootDiskMatcher(input *api.BaremetalRootDiskMatcher) error {
- if input.SizeMBRange != nil {
- if input.SizeMBRange.Start > input.SizeMBRange.End {
- return errors.Errorf("size_mb_range.start %d is large than size_mb_range.end %d", input.SizeMBRange.Start, input.SizeMBRange.End)
- }
- }
- return nil
- }
|