func (m DeviceClassManager) DeviceClass(dcName string) (*DeviceClass, error) {
	if dcName == topolvm.DefaultDeviceClassName {
		return m.defaultDeviceClass, nil
	}
	if v, ok := m.deviceClassByName[dcName]; ok {
		return v, nil
	}
	return nil, ErrNotFound
}
DeviceClass returns the device-class by its name
package lvmd
import (
	"errors"
	"fmt"
	"regexp"
	"github.com/topolvm/topolvm"
)
var ErrNotFound = errors.New("device-class not found")
const defaultSpareGB = 10
var qualifiedNameRegexp = regexp.MustCompile("^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$")
var stripeSizeRegexp = regexp.MustCompile("(?i)^([0-9]*)(k|m|g|t|p|e|b|s)?$")
type DeviceClass struct {
	Name string `json:"name"`
	VolumeGroup string `json:"volume-group"`
	Default bool `json:"default"`
	SpareGB *uint64 `json:"spare-gb"`
	Stripe *uint `json:"stripe"`
	StripeSize string `json:"stripe-size"`
}
func (c DeviceClass) GetSpare() uint64 {
	if c.SpareGB == nil {
		return defaultSpareGB << 30
	}
	return *c.SpareGB << 30
}
func ValidateDeviceClasses(deviceClasses []*DeviceClass) error {
	if len(deviceClasses) < 1 {
		return errors.New("should have at least one device-class")
	}
	var countDefault = 0
	dcNames := make(map[string]bool)
	vgNames := make(map[string]bool)
	for _, dc := range deviceClasses {
		if len(dc.Name) == 0 {
			return errors.New("device-class name should not be empty")
		} else if len(dc.Name) > 63 {
			return fmt.Errorf("device-class name is too long: %s", dc.Name)
		}
		if !qualifiedNameRegexp.MatchString(dc.Name) {
			return fmt.Errorf("device-class name should consist of alphanumeric characters, '-', '_' or '.', and should start and end with an alphanumeric character: %s", dc.Name)
		}
		if len(dc.VolumeGroup) == 0 {
			return fmt.Errorf("volume group name should not be empty: %s", dc.Name)
		}
		if dc.Default {
			countDefault++
		}
		if dcNames[dc.Name] {
			return fmt.Errorf("duplicate device-class name: %s", dc.Name)
		}
		if vgNames[dc.VolumeGroup] {
			return fmt.Errorf("duplicate volume group name: %s, %s", dc.Name, dc.VolumeGroup)
		}
		dcNames[dc.Name] = true
		vgNames[dc.VolumeGroup] = true
		if dc.StripeSize != "" && !stripeSizeRegexp.MatchString(dc.StripeSize) {
			return fmt.Errorf("stripe-size format is \"Size[k|UNIT]\": %s", dc.Name)
		}
	}
	if countDefault != 1 {
		return errors.New("should have only one default device-class")
	}
	return nil
}
type DeviceClassManager struct {
	defaultDeviceClass  *DeviceClass
	deviceClassByName   map[string]*DeviceClass
	deviceClassByVGName map[string]*DeviceClass
}
func NewDeviceClassManager(deviceClasses []*DeviceClass) *DeviceClassManager {
	dcm := DeviceClassManager{}
	dcm.deviceClassByName = make(map[string]*DeviceClass)
	dcm.deviceClassByVGName = make(map[string]*DeviceClass)
	for _, dc := range deviceClasses {
		if dc.Default {
			dcm.defaultDeviceClass = dc
		}
		dcm.deviceClassByName[dc.Name] = dc
		dcm.deviceClassByVGName[dc.VolumeGroup] = dc
	}
	return &dcm
}