package createconfig import ( "fmt" "strconv" "strings" "github.com/docker/go-units" "github.com/opencontainers/runc/libcontainer/configs" spec "github.com/opencontainers/runtime-spec/specs-go" ) // weightDevice is a structure that holds device:weight pair type weightDevice struct { path string weight uint16 } func (w *weightDevice) String() string { return fmt.Sprintf("%s:%d", w.path, w.weight) } // validateweightDevice validates that the specified string has a valid device-weight format // for blkio-weight-device flag func validateweightDevice(val string) (*weightDevice, error) { split := strings.SplitN(val, ":", 2) if len(split) != 2 { return nil, fmt.Errorf("bad format: %s", val) } if !strings.HasPrefix(split[0], "/dev/") { return nil, fmt.Errorf("bad format for device path: %s", val) } weight, err := strconv.ParseUint(split[1], 10, 0) if err != nil { return nil, fmt.Errorf("invalid weight for device: %s", val) } if weight > 0 && (weight < 10 || weight > 1000) { return nil, fmt.Errorf("invalid weight for device: %s", val) } return &weightDevice{ path: split[0], weight: uint16(weight), }, nil } // throttleDevice is a structure that holds device:rate_per_second pair type throttleDevice struct { path string rate uint64 } func (t *throttleDevice) String() string { return fmt.Sprintf("%s:%d", t.path, t.rate) } // validateBpsDevice validates that the specified string has a valid device-rate format // for device-read-bps and device-write-bps flags func validateBpsDevice(val string) (*throttleDevice, error) { split := strings.SplitN(val, ":", 2) if len(split) != 2 { return nil, fmt.Errorf("bad format: %s", val) } if !strings.HasPrefix(split[0], "/dev/") { return nil, fmt.Errorf("bad format for device path: %s", val) } rate, err := units.RAMInBytes(split[1]) if err != nil { return nil, fmt.Errorf("invalid rate for device: %s. The correct format is :[]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb", val) } if rate < 0 { return nil, fmt.Errorf("invalid rate for device: %s. The correct format is :[]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb", val) } return &throttleDevice{ path: split[0], rate: uint64(rate), }, nil } // validateIOpsDevice validates that the specified string has a valid device-rate format // for device-write-iops and device-read-iops flags func validateIOpsDevice(val string) (*throttleDevice, error) { //nolint split := strings.SplitN(val, ":", 2) if len(split) != 2 { return nil, fmt.Errorf("bad format: %s", val) } if !strings.HasPrefix(split[0], "/dev/") { return nil, fmt.Errorf("bad format for device path: %s", val) } rate, err := strconv.ParseUint(split[1], 10, 64) if err != nil { return nil, fmt.Errorf("invalid rate for device: %s. The correct format is :. Number must be a positive integer", val) } if rate < 0 { return nil, fmt.Errorf("invalid rate for device: %s. The correct format is :. Number must be a positive integer", val) } return &throttleDevice{ path: split[0], rate: uint64(rate), }, nil } func getLoggingPath(opts []string) string { for _, opt := range opts { arr := strings.SplitN(opt, "=", 2) if len(arr) == 2 { if strings.TrimSpace(arr[0]) == "path" { return strings.TrimSpace(arr[1]) } } } return "" } // Device transforms a libcontainer configs.Device to a specs.LinuxDevice object. func Device(d *configs.Device) spec.LinuxDevice { return spec.LinuxDevice{ Type: string(d.Type), Path: d.Path, Major: d.Major, Minor: d.Minor, FileMode: fmPtr(int64(d.FileMode)), UID: u32Ptr(int64(d.Uid)), GID: u32Ptr(int64(d.Gid)), } }