state/meterstatus: Wired up meter status with metrics manager status #1677

Merged
merged 6 commits into from Mar 24, 2015
@@ -769,8 +769,8 @@ func (s *unitSuite) TestWatchMeterStatus(c *gc.C) {
err := mm.IncrementConsecutiveErrors()
c.Assert(err, jc.ErrorIsNil)
}
- code, _ := mm.MeterStatus()
- c.Assert(code, gc.Equals, state.MeterAmber) // Confirm meter status has changed
+ status := mm.MeterStatus()
+ c.Assert(status.Code, gc.Equals, state.MeterAmber) // Confirm meter status has changed
wc.AssertOneChange()
statetesting.AssertStop(c, w)
@@ -190,19 +190,17 @@ func (s *SenderSuite) TestMeterStatus(c *gc.C) {
_ = s.Factory.MakeMetric(c, &factory.MetricParams{Unit: s.unit, Sent: false})
- status, info, err := s.unit.GetMeterStatus()
+ status, err := s.unit.GetMeterStatus()
c.Assert(err, jc.ErrorIsNil)
- c.Assert(status, gc.Equals, "NOT SET")
- c.Assert(info, gc.Equals, "")
+ c.Assert(status.Code, gc.Equals, state.MeterNotSet)
var sender metricsender.DefaultSender
err = metricsender.SendMetrics(s.State, &sender, 10)
c.Assert(err, jc.ErrorIsNil)
- status, info, err = s.unit.GetMeterStatus()
+ status, err = s.unit.GetMeterStatus()
c.Assert(err, jc.ErrorIsNil)
- c.Assert(status, gc.Equals, "GREEN")
- c.Assert(info, gc.Equals, "")
+ c.Assert(status.Code, gc.Equals, state.MeterGreen)
}
// TestMeterStatusInvalid checks that the metric sender deals with invalid
@@ -236,30 +234,26 @@ func (s *SenderSuite) TestMeterStatusInvalid(c *gc.C) {
_ = s.Factory.MakeMetric(c, &factory.MetricParams{Unit: unit3, Sent: false})
for _, unit := range []*state.Unit{unit1, unit2, unit3} {
- status, info, err := unit.GetMeterStatus()
+ status, err := unit.GetMeterStatus()
c.Assert(err, jc.ErrorIsNil)
- c.Assert(status, gc.Equals, "NOT SET")
- c.Assert(info, gc.Equals, "")
+ c.Assert(status.Code, gc.Equals, state.MeterNotSet)
}
var sender metricsender.DefaultSender
err := metricsender.SendMetrics(s.State, &sender, 10)
c.Assert(err, jc.ErrorIsNil)
- status, info, err := unit1.GetMeterStatus()
+ status, err := unit1.GetMeterStatus()
c.Assert(err, jc.ErrorIsNil)
- c.Assert(status, gc.Equals, "GREEN")
- c.Assert(info, gc.Equals, "")
+ c.Assert(status.Code, gc.Equals, state.MeterGreen)
- status, info, err = unit2.GetMeterStatus()
+ status, err = unit2.GetMeterStatus()
c.Assert(err, jc.ErrorIsNil)
- c.Assert(status, gc.Equals, "NOT SET")
- c.Assert(info, gc.Equals, "")
+ c.Assert(status.Code, gc.Equals, state.MeterNotSet)
- status, info, err = unit3.GetMeterStatus()
+ status, err = unit3.GetMeterStatus()
c.Assert(err, jc.ErrorIsNil)
- c.Assert(status, gc.Equals, "NOT SET")
- c.Assert(info, gc.Equals, "")
+ c.Assert(status.Code, gc.Equals, state.MeterNotSet)
}
@@ -1263,17 +1263,16 @@ func (u *uniterBaseAPI) GetMeterStatus(args params.Entities) (params.MeterStatus
continue
}
err = common.ErrPerm
- var code string
- var info string
+ var status state.MeterStatus
if canAccess(unitTag) {
var unit *state.Unit
unit, err = u.getUnit(unitTag)
if err == nil {
- code, info, err = unit.GetMeterStatus()
+ status, err = unit.GetMeterStatus()
}
+ result.Results[i].Code = status.Code.String()
+ result.Results[i].Info = status.Info
}
- result.Results[i].Code = code
- result.Results[i].Info = info
result.Results[i].Error = common.ServerError(err)
}
return result, nil
View
@@ -47,6 +47,7 @@ var (
MultiEnvCollections = multiEnvCollections
PickAddress = &pickAddress
AddVolumeOp = (*State).addVolumeOp
+ CombineMeterStatus = combineMeterStatus
)
type (
View
@@ -13,27 +13,75 @@ import (
var meterStatusLogger = loggo.GetLogger("juju.state.meterstatus")
+// MeterStatus represents the metering status of a unit.
+type MeterStatus struct {
+ Code MeterStatusCode
+ Info string
+}
+
+// Severity returns relative severity of the meter status.
+func (m *MeterStatus) Severity() int {
+ return m.Code.Severity()
+}
+
// MeterStatusCode represents the meter status code of a unit.
-type MeterStatusCode string
+// The int value represents its relative severity when compared to
+// other MeterStatusCodes.
+type MeterStatusCode int
+
+// Severity returns the relative severity.
+func (m MeterStatusCode) Severity() int {
+ return int(m)
+}
+
+// String returns a human readable string representation of the meter status.
+func (m MeterStatusCode) String() string {
+ s, ok := meterString[m]
+ if !ok {
+ return MeterNotAvailable.String()
+ }
+ return s
+}
+
+// MeterStatusFromString returns a valid MeterStatusCode given a string representation.
+func MeterStatusFromString(str string) MeterStatusCode {
+ for m, s := range meterString {
+ if s == str {
+ return m
+ }
+ }
+ return MeterNotAvailable
+}
+// This const block defines the relative severities of the valid MeterStatusCodes in ascending order.
const (
- MeterNotSet MeterStatusCode = "NOT SET"
- MeterNotAvailable MeterStatusCode = "NOT AVAILABLE"
- MeterGreen MeterStatusCode = "GREEN"
- MeterAmber MeterStatusCode = "AMBER"
- MeterRed MeterStatusCode = "RED"
+ MeterGreen MeterStatusCode = iota
+ MeterNotSet
+ MeterAmber
+ MeterRed
+ MeterNotAvailable
+)
+
+var (
+ meterString = map[MeterStatusCode]string{
+ MeterGreen: "GREEN",
+ MeterNotSet: "NOT SET",
+ MeterAmber: "AMBER",
+ MeterNotAvailable: "NOT AVAILABLE",
+ MeterRed: "RED",
+ }
)
type meterStatusDoc struct {
- DocID string `bson:"_id"`
- EnvUUID string `bson:"env-uuid"`
- Code MeterStatusCode `bson:"code"`
- Info string `bson:"info"`
+ DocID string `bson:"_id"`
+ EnvUUID string `bson:"env-uuid"`
+ Code string `bson:"code"`
+ Info string `bson:"info"`
}
// SetMeterStatus sets the meter status for the unit.
-func (u *Unit) SetMeterStatus(codeRaw, info string) error {
- code := MeterStatusCode(codeRaw)
+func (u *Unit) SetMeterStatus(codeStr, info string) error {
+ code := MeterStatusFromString(codeStr)
switch code {
case MeterGreen, MeterAmber, MeterRed:
default:
@@ -43,7 +91,7 @@ func (u *Unit) SetMeterStatus(codeRaw, info string) error {
if err != nil {
return errors.Annotatef(err, "cannot update meter status for unit %s", u.Name())
}
- if meterDoc.Code == code && meterDoc.Info == info {
+ if meterDoc.Code == code.String() && meterDoc.Info == info {
return nil
}
@@ -57,7 +105,7 @@ func (u *Unit) SetMeterStatus(codeRaw, info string) error {
if err != nil {
return nil, errors.Annotatef(err, "cannot update meter status for unit %s", u.Name())
}
- if meterDoc.Code == code && meterDoc.Info == info {
+ if meterDoc.Code == code.String() && meterDoc.Info == info {
return nil, jujutxn.ErrNoOperations
}
}
@@ -70,7 +118,7 @@ func (u *Unit) SetMeterStatus(codeRaw, info string) error {
C: meterStatusC,
Id: u.st.docID(u.globalKey()),
Assert: txn.DocExists,
- Update: bson.D{{"$set", bson.D{{"code", code}, {"info", info}}}},
+ Update: bson.D{{"$set", bson.D{{"code", code.String()}, {"info", info}}}},
}}, nil
}
return errors.Annotatef(u.st.run(buildTxn), "cannot set meter state for unit %s", u.Name())
@@ -99,12 +147,33 @@ func removeMeterStatusOp(st *State, globalKey string) txn.Op {
}
// GetMeterStatus returns the meter status for the unit.
-func (u *Unit) GetMeterStatus() (code, info string, err error) {
+func (u *Unit) GetMeterStatus() (MeterStatus, error) {
+ mm, err := u.st.MetricsManager()
+ if err != nil {
+ return MeterStatus{MeterNotAvailable, ""}, errors.Annotatef(err, "cannot retrieve meter status for metrics manager")
+ }
+
+ mmStatus := mm.MeterStatus()
+ if mmStatus.Code == MeterRed {
+ return mmStatus, nil
+ }
+
status, err := u.getMeterStatusDoc()
if err != nil {
- return string(MeterNotAvailable), "", errors.Annotatef(err, "cannot retrieve meter status for unit %s", u.Name())
+ return MeterStatus{MeterNotAvailable, ""}, errors.Annotatef(err, "cannot retrieve meter status for unit %s", u.Name())
+ }
+
+ code := MeterStatusFromString(status.Code)
+
+ unitMeterStatus := MeterStatus{code, status.Info}
+ return combineMeterStatus(mmStatus, unitMeterStatus), nil
+}
+
+func combineMeterStatus(a, b MeterStatus) MeterStatus {
+ if a.Severity() > b.Severity() {
+ return a
}
- return string(status.Code), status.Info, nil
+ return b
}
func (u *Unit) getMeterStatusDoc() (*meterStatusDoc, error) {
Oops, something went wrong.