Skip to content

Commit

Permalink
storage: create common constraint values struct
Browse files Browse the repository at this point in the history
  • Loading branch information
axw committed Jan 5, 2015
1 parent 5a183bc commit d444d0a
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 76 deletions.
2 changes: 1 addition & 1 deletion dependencies.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ github.com/juju/schema git 27a52be50766490a6fd3531865095fda6c0eeb6d
github.com/juju/syslog git 2b69d6582feb16ff8b6d644495e16c2d8314fcb8
github.com/juju/testing git 839334678c08487fb1c6ab032893fc8c85d74756
github.com/juju/txn git e02f26c56cfb81c7c1236df499deebb0369bd97c
github.com/juju/utils git c1f38bc81aa18a8fff86ffbd8d5587b218118d3d
github.com/juju/utils git 37016f78b9989f99222a5e09a26e25db124c1b17 2014-12-05T10:56:08+08:00
gopkg.in/check.v1 git 91ae5f88a67b14891cfd43895b01164f6c120420
gopkg.in/juju/charm.v4 git f7e5613ff75457d2700d1c3269546cc903ea0471
gopkg.in/mgo.v2 git dc255bb679efa273b6544a03261c4053505498a4
Expand Down
60 changes: 27 additions & 33 deletions storage/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,34 @@ var logger = loggo.GetLogger("juju.storage")

// Constraints describes a set of storage constraints.
type Constraints struct {
// Size is the preferred size of the storage in MiB.
Size uint64
// Source is the name of the storage source (ebs, ceph, ...) that
// must provide the storage, or "" if any source may be used.
Source string

// MinimumSize is the minimum size of the storage in MiB.
MinimumSize uint64
// Minimum is the minimum acceptable values for each constraint variable.
Minimum ConstraintValues

// Count is the preferred number of instances of the
// storage to create.
Count uint64
// Preferred is the preferred values for each constraint variable.
Preferred ConstraintValues
}

// MinimumCount is the minimum number of instances of the
// storage to create.
MinimumCount uint64
// ConstraintValues describes the constraints on individual storage
// characteristics.
type ConstraintValues struct {
// Size is the size of the storage in MiB.
Size uint64

// Count is the number of instances of the storage to create.
Count uint64

// Persistent indicates that the storage should be persistent
// beyond the lifetime of the machine that it is initially
// attached to.
Persistent bool

// RequirePersistent indicates that the storage must be persistent.
RequirePersistent bool

// IOPS is the preferred number of IOPS (I/O Operations Per Second)
// that the storage should be capable of.
// IOPS is the number of IOPS (I/O Operations Per Second) that the
// storage should be capable of.
IOPS uint64

// MinimumIOPS is the minimum number of IOPS that the storage must
// be capable of.
MinimumIOPS uint64

// Source is the name of the storage source (ebs, ceph, ...) that
// must provide the storage, or "" if any source may be used.
Source string
}

const (
Expand Down Expand Up @@ -105,18 +100,18 @@ func ParseConstraints(s string) (Constraints, error) {
if countSizeMatch != nil {
if countSizeMatch[1] != "" {
if countSizeMatch[1][0] != '-' {
cons.Count, err = strconv.ParseUint(countSizeMatch[1], 10, 64)
cons.Preferred.Count, err = strconv.ParseUint(countSizeMatch[1], 10, 64)
if err != nil {
return cons, errors.Annotatef(err, "cannot parse count %q", countSizeMatch[1])
}
}
if cons.Count == 0 {
if cons.Preferred.Count == 0 {
return cons, errors.Errorf("count must be greater than zero, got %q", countSizeMatch[1])
}
} else {
cons.Count = 1
cons.Preferred.Count = 1
}
cons.Size, err = utils.ParseSize(countSizeMatch[2])
cons.Preferred.Size, err = utils.ParseSize(countSizeMatch[2])
if err != nil {
return cons, errors.Annotate(err, "cannot parse size")
}
Expand All @@ -128,10 +123,10 @@ func ParseConstraints(s string) (Constraints, error) {
switch {
case field == "":
case field == "persistent":
cons.Persistent = true
cons.Preferred.Persistent = true
case strings.HasPrefix(strings.ToLower(field), "iops:"):
value := field[len("iops:"):]
cons.IOPS, err = strconv.ParseUint(value, 10, 64)
cons.Preferred.IOPS, err = strconv.ParseUint(value, 10, 64)
if err != nil {
return cons, errors.Annotatef(err, "cannot parse IOPS %q", value)
}
Expand All @@ -140,9 +135,8 @@ func ParseConstraints(s string) (Constraints, error) {
}
}

cons.MinimumCount = cons.Count
cons.MinimumSize = cons.Size
cons.RequirePersistent = cons.Persistent
cons.MinimumIOPS = cons.IOPS
// Explicitly specified constraints are always required;
// the minimum is the same as the preferred.
cons.Minimum = cons.Preferred
return cons, nil
}
88 changes: 46 additions & 42 deletions storage/constraints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,77 +16,78 @@ var _ = gc.Suite(&ConstraintsSuite{})

func (s *ConstraintsSuite) TestParseConstraintsStorageSource(c *gc.C) {
s.testParse(c, "provider:1M", storage.Constraints{
Source: "provider",
Count: 1,
MinimumCount: 1,
Size: 1,
MinimumSize: 1,
Source: "provider",
Preferred: storage.ConstraintValues{
Count: 1,
Size: 1,
},
})
s.testParse(c, "provider0123:", storage.Constraints{
Source: "provider0123",
})
s.testParse(c, ":", storage.Constraints{})
s.testParse(c, "1M", storage.Constraints{
Count: 1,
MinimumCount: 1,
Size: 1,
MinimumSize: 1,
Preferred: storage.ConstraintValues{
Size: 1,
Count: 1,
},
})
}

func (s *ConstraintsSuite) TestParseConstraintsCountSize(c *gc.C) {
s.testParse(c, "s:1G", storage.Constraints{
Source: "s",
Count: 1,
MinimumCount: 1,
Size: 1024,
MinimumSize: 1024,
Source: "s",
Preferred: storage.ConstraintValues{
Count: 1,
Size: 1024,
},
})
s.testParse(c, "s:1x0.5T", storage.Constraints{
Source: "s",
Count: 1,
MinimumCount: 1,
Size: 1024 * 512,
MinimumSize: 1024 * 512,
Source: "s",
Preferred: storage.ConstraintValues{
Count: 1,
Size: 1024 * 512,
},
})
s.testParse(c, "s:3x0.125P", storage.Constraints{
Source: "s",
Count: 3,
MinimumCount: 3,
Size: 1024 * 1024 * 128,
MinimumSize: 1024 * 1024 * 128,
Source: "s",
Preferred: storage.ConstraintValues{
Count: 3,
Size: 1024 * 1024 * 128,
},
})
}

func (s *ConstraintsSuite) TestParseConstraintsOptions(c *gc.C) {
s.testParse(c, "s:1M,", storage.Constraints{
Source: "s",
Count: 1,
MinimumCount: 1,
Size: 1,
MinimumSize: 1,
Source: "s",
Preferred: storage.ConstraintValues{
Count: 1,
Size: 1,
},
})
s.testParse(c, "s:anyoldjunk", storage.Constraints{
Source: "s",
})
s.testParse(c, "s:persistent", storage.Constraints{
Source: "s",
Persistent: true,
RequirePersistent: true,
Source: "s",
Preferred: storage.ConstraintValues{
Persistent: true,
},
})
s.testParse(c, "s:persistent,iops:10000", storage.Constraints{
Source: "s",
Persistent: true,
RequirePersistent: true,
IOPS: 10000,
MinimumIOPS: 10000,
Source: "s",
Preferred: storage.ConstraintValues{
Persistent: true,
IOPS: 10000,
},
})
s.testParse(c, "s:iops:10000,persistent", storage.Constraints{
Source: "s",
Persistent: true,
RequirePersistent: true,
IOPS: 10000,
MinimumIOPS: 10000,
Source: "s",
Preferred: storage.ConstraintValues{
Persistent: true,
IOPS: 10000,
},
})
}

Expand All @@ -101,6 +102,9 @@ func (s *ConstraintsSuite) TestParseConstraintsSizeRange(c *gc.C) {
}

func (*ConstraintsSuite) testParse(c *gc.C, s string, expect storage.Constraints) {
// ParseConstraints should always return min=preferred. Avoid repetitious
// tests by setting the expectation here.
expect.Minimum = expect.Preferred
cons, err := storage.ParseConstraints(s)
c.Check(err, jc.ErrorIsNil)
c.Check(cons, gc.DeepEquals, expect)
Expand Down

0 comments on commit d444d0a

Please sign in to comment.