uptime function in gauge given a parameter of billable states (will be renamed to tracked later). Also some code clean up and formatting done.

This commit is contained in:
adriant 2014-01-15 15:05:53 +13:00
parent 8751f45163
commit 5cb1ba97f3
2 changed files with 48 additions and 24 deletions

View File

@ -604,21 +604,23 @@ class Gauge(Artifact):
# print totals # print totals
return sum(totals) return sum(totals)
def uptime(self): def uptime(self, billable):
"""Calculates uptime accurately for the given 'billable' states. """Calculates uptime accurately for the given 'billable' states.
Will ignore all other states. - Will ignore all other states.
- Relies heavily on the existence of a state meter.""" - Relies heavily on the existence of a state meter, and
should only ever be called on the state meter.
# this NEEDS to be moved to a config file Returns: uptime in seconds"""
billable = [1, 2, 3, 6, 7]
usage = sorted(self.usage, key=lambda x: x["timestamp"]) usage = sorted(self.usage, key=lambda x: x["timestamp"])
last = usage[0] last = usage[0]
try: try:
last["timestamp"] = datetime.datetime.strptime(last["timestamp"], date_format) last["timestamp"] = datetime.datetime.strptime(last["timestamp"],
date_format)
except ValueError: except ValueError:
last["timestamp"] = datetime.datetime.strptime(last["timestamp"], other_date_format) last["timestamp"] = datetime.datetime.strptime(last["timestamp"],
other_date_format)
except TypeError: except TypeError:
pass pass
@ -626,15 +628,28 @@ class Gauge(Artifact):
for val in usage[1:]: for val in usage[1:]:
try: try:
val["timestamp"] = datetime.datetime.strptime(val["timestamp"], date_format) val["timestamp"] = datetime.datetime.strptime(val["timestamp"],
date_format)
except ValueError: except ValueError:
val["timestamp"] = datetime.datetime.strptime(val["timestamp"], other_date_format) val["timestamp"] = datetime.datetime.strptime(val["timestamp"],
other_date_format)
except TypeError: except TypeError:
pass pass
if val["counter_volume"] in billable: if val["counter_volume"] in billable:
difference = val["timestamp"] - last["timestamp"] difference = val["timestamp"] - last["timestamp"]
uptime = uptime + difference.seconds
# TODO:
# possibly might need to account for sudden jumps
# caused due to ceilometer down time:
if difference > datetime.timedelta(hours=1):
# the timedelta should be the ceilometer interval.
# do nothing if different greater than twice interval?
# or just add interval length to uptime.
pass
else:
# otherwise just add difference.
uptime = uptime + difference.seconds
last = val last = val

View File

@ -5,6 +5,7 @@ from sqlalchemy.orm import relationship, backref
from decimal import * from decimal import *
import math import math
class Resource(Base): class Resource(Base):
__tablename__ = "resources" __tablename__ = "resources"
@ -33,8 +34,8 @@ class BaseModelConstruct(object):
def get(self, name): def get(self, name):
# Returns a given name value thing? # Returns a given name value thing?
# Based on patterning, this is expected to be a dict of usage information # Based on patterning, this is expected to be a dict of usage
# based on a meter, I guess? # information based on a meter, I guess?
return getattr(self, name) return getattr(self, name)
def _fetch_meter_name(self, name): def _fetch_meter_name(self, name):
@ -68,7 +69,8 @@ class VM(BaseModelConstruct):
# The only relevant meters of interest are the type of the interest # The only relevant meters of interest are the type of the interest
# and the amount of network we care about. # and the amount of network we care about.
# Oh, and floating IPs. # Oh, and floating IPs.
relevant_meters = ["state", "instance", "cpu", "instance:<type>", "network.incoming.bytes", "network.outgoing.bytes"] relevant_meters = ["state", "instance", "cpu", "instance:<type>",
"network.incoming.bytes", "network.outgoing.bytes"]
def _fetch_meter_name(self, name): def _fetch_meter_name(self, name):
if name == "instance:<type>": if name == "instance:<type>":
@ -81,11 +83,16 @@ class VM(BaseModelConstruct):
@property @property
def amount(self): def amount(self):
seconds = self.usage()['state'].uptime()
# this NEEDS to be moved to a config file or
# possibly be queried from Clerk?
billable = [1, 2, 3, 6, 7]
seconds = self.usage()['state'].uptime(billable)
# in hours, rounded up: # in hours, rounded up:
uptime = math.ceil((seconds/60.0)/60.0) uptime = math.ceil((seconds / 60.0) / 60.0)
class Amount(object): class Amount(object):
def volume(self): def volume(self):
return Decimal(uptime) return Decimal(uptime)
@ -99,10 +106,10 @@ class VM(BaseModelConstruct):
@property @property
def type(self): def type(self):
# TODO FIgure out what the hell is going on with ceilometer here, # TODO FIgure out what the hell is going on with ceilometer here,
# and why flavor.name isn't always there, and why sometimes instance_type # and why flavor.name isn't always there, and why
# is needed instead.... # sometimes instance_type is needed instead....
try: try:
# print "\"flavor.name\" was used" # print "\"flavor.name\" was used"
return self._raw["metadata"]["flavor.name"] return self._raw["metadata"]["flavor.name"]
except KeyError: except KeyError:
@ -139,21 +146,22 @@ class VM(BaseModelConstruct):
def name(self): def name(self):
return self._raw["metadata"]["display_name"] return self._raw["metadata"]["display_name"]
class Object(BaseModelConstruct): class Object(BaseModelConstruct):
relevant_meters = ["storage.objects.size"] relevant_meters = ["storage.objects.size"]
type = "object" # object storage type = "object" # object storage
@property @property
def size(self): def size(self):
# How much use this had. # How much use this had.
return self._raw.meter("storage.objects.size", self.start, self.end).volume() return self._raw.meter("storage.objects.size",
self.start, self.end).volume()
# Size is a gauge measured every 10 minutes. # Size is a gauge measured every 10 minutes.
# So that needs to be compressed to 60-minute intervals # So that needs to be compressed to 60-minute intervals
class Volume(BaseModelConstruct): class Volume(BaseModelConstruct):
relevant_meters = ["volume.size"] relevant_meters = ["volume.size"]
@ -167,5 +175,6 @@ class Volume(BaseModelConstruct):
# Size of the thing over time. # Size of the thing over time.
return self._raw.meter("volume.size", self.start, self.end).volume() return self._raw.meter("volume.size", self.start, self.end).volume()
class Network(BaseModelConstruct): class Network(BaseModelConstruct):
relevant_meters = ["ip.floating"] relevant_meters = ["ip.floating"]