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:
parent
8751f45163
commit
5cb1ba97f3
@ -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
|
||||||
|
|
||||||
|
@ -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"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user