func ParseConstraints(s string) (Constraints, error) {
	var cons Constraints
	fields := strings.Split(s, ",")
	for _, field := range fields {
		if field == "" {
			continue
		}
		if IsValidPoolName(field) {
			if cons.Pool != "" {
				return cons, errors.NotValidf("pool name is already set to %q, new value %q", cons.Pool, field)
			} else {
				cons.Pool = field
			}
			continue
		}
		if count, ok, err := parseCount(field); ok {
			if err != nil {
				return cons, errors.Annotate(err, "cannot parse count")
			}
			cons.Count = count
			continue
		}
		if size, ok, err := parseSize(field); ok {
			if err != nil {
				return cons, errors.Annotate(err, "cannot parse size")
			}
			cons.Size = size
			continue
		}
		return cons, errors.NotValidf("unrecognized storage constraint %q", field)
	}
	if cons.Count == 0 && cons.Size == 0 && cons.Pool == "" {
		return Constraints{}, errors.New("storage constraints require at least one field to be specified")
	}
	if cons.Count == 0 {
		cons.Count = 1
	}
	return cons, nil
}
// ParseConstraints parses the specified string and creates a
// Constraints structure.
//
// The acceptable format for storage constraints is a comma separated
// sequence of: POOL, COUNT, and SIZE, where
//
//    POOL identifies the storage pool. POOL can be a string
//    starting with a letter, followed by zero or more digits
//    or letters optionally separated by hyphens.
//
//    COUNT is a positive integer indicating how many instances
//    of the storage to create. If unspecified, and SIZE is
//    specified, COUNT defaults to 1.
//
//    SIZE describes the minimum size of the storage instances to
//    create. SIZE is a floating point number and multiplier from
//    the set (M, G, T, P, E, Z, Y), which are all treated as
//    powers of 1024.
ParseConstraints parses the specified string and creates a
Constraints structure.

The acceptable format for storage constraints is a comma separated
sequence of: POOL, COUNT, and SIZE, where

POOL identifies the storage pool. POOL can be a string
starting with a letter, followed by zero or more digits
or letters optionally separated by hyphens.

COUNT is a positive integer indicating how many instances
of the storage to create. If unspecified, and SIZE is
specified, COUNT defaults to 1.

SIZE describes the minimum size of the storage instances to
create. SIZE is a floating point number and multiplier from
the set (M, G, T, P, E, Z, Y), which are all treated as
powers of 1024.
// ParseConstraints parses the specified string and creates a // Constraints structure . // // The acceptable format for storage constraints is a comma separated // sequence of : POOL COUNT and SIZE where // // POOL identifies the storage pool . POOL can be a string // starting with a letter followed by zero or more digits // or letters optionally separated by hyphens . // // COUNT is a positive integer indicating how many instances // of the storage to create . If unspecified and SIZE is // specified COUNT defaults to 1 . // // SIZE describes the minimum size of the storage instances to // create . SIZE is a floating point number and multiplier from // the set ( M G T P E Z Y ) which are all treated as // powers of 1024 .
func ParseConstraints(s string) (Constraints, error) {
	var cons Constraints
	fields := strings.Split(s, ",")
	for _, field := range fields {
		if field == "" {
			continue
		}
		if IsValidPoolName(field) {
			if cons.Pool != "" {
				return cons, errors.NotValidf("pool name is already set to %q, new value %q", cons.Pool, field)
			} else {
				cons.Pool = field
			}
			continue
		}
		if count, ok, err := parseCount(field); ok {
			if err != nil {
				return cons, errors.Annotate(err, "cannot parse count")
			}
			cons.Count = count
			continue
		}
		if size, ok, err := parseSize(field); ok {
			if err != nil {
				return cons, errors.Annotate(err, "cannot parse size")
			}
			cons.Size = size
			continue
		}
		return cons, errors.NotValidf("unrecognized storage constraint %q", field)
	}
	if cons.Count == 0 && cons.Size == 0 && cons.Pool == "" {
		return Constraints{}, errors.New("storage constraints require at least one field to be specified")
	}
	if cons.Count == 0 {
		cons.Count = 1
	}
	return cons, nil
}
func ParseConstraints ( s string ) ( Constraints , error ) { var cons Constraints fields := strings . Split ( s , " " ) for _ , field := range fields { if field == " " { continue } if IsValidPoolName ( field ) { if cons . Pool != " " { return cons , errors . NotValidf ( " " , cons . Pool , field ) } else { cons . Pool = field } continue } if count , ok , err := parseCount ( field ) ; ok { if err != nil { return cons , errors . Annotate ( err , " " ) } cons . Count = count continue } if size , ok , err := parseSize ( field ) ; ok { if err != nil { return cons , errors . Annotate ( err , " " ) } cons . Size = size continue } return cons , errors . NotValidf ( " " , field ) } if cons . Count == 0 && cons . Size == 0 && cons . Pool == " " { return Constraints { } , errors . New ( " " ) } if cons . Count == 0 { cons . Count = 1 } return cons , nil }
ParseConstraints parses the specified string and creates a
Constraints structure.
ParseConstraints parses the specified string and creates a Constraints structure .