distil/artifice/models/resources.py

184 lines
5.1 KiB
Python

from decimal import Decimal
import math
class BaseModelConstruct(object):
def __init__(self, raw, start, end):
# raw is the raw data for this
self._raw = raw
self._location = None
self.start = start
self.end = end
@property
def resource_id(self):
return self._raw.resource.resource_id
@property
def tenant_id(self):
return self._raw.resource.project_id
def __getitem__(self, item):
return self._raw[item]
def get(self, name):
# Returns a given name value thing?
# Based on patterning, this is expected to be a dict of usage
# information based on a meter, I guess?
return getattr(self, name)
def usage(self):
dct = {}
for meter in self.relevant_meters:
try:
vol = self._raw.meter(meter, self.start, self.end).volume()
dct[meter] = vol
except AttributeError:
# This is OK. We're not worried about non-existent meters,
# I think. For now, anyway.
pass
return dct
def save(self):
for meter in self.relevant_meters:
try:
self._raw.meter(meter, self.start, self.end).save()
except AttributeError:
# This is OK. We're not worried about non-existent meters,
# I think. For now, anyway.
pass
def to_mb(bytes):
# function to make code easier to understand elsewhere.
return (bytes / 1000) / 1000
class VM(BaseModelConstruct):
# The only relevant meters of interest are the type of the interest
# and the amount of network we care about.
# Oh, and floating IPs.
relevant_meters = ["state"]
usage_strategies = {"uptime": {"usage": "uptime", "service": "flavor"}}
type = "virtual_machine"
@property
def uptime(self):
# this NEEDS to be moved to a config file or
# possibly be queried from Clerk?
tracked = [1, 2, 3, 6, 7]
seconds = self.usage()["state"].uptime(tracked)
# in hours, rounded up:
uptime = math.ceil((seconds / 60.0) / 60.0)
return Decimal(uptime)
@property
def flavor(self):
# 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 is needed instead....
try:
# print "\"flavor.name\" was used"
return self._raw["metadata"]["flavor.name"].replace(".", "_")
except KeyError:
# print "\"instance_type\" was used"
return self._raw["metadata"]["instance_type"].replace(".", "_")
@property
def memory(self):
return self._raw["metadata"]["memory"]
@property
def cpus(self):
return self._raw["metadata"]["vcpus"]
@property
def state(self):
return self._raw["metadata"]["state"]
@property
def name(self):
return self._raw["metadata"]["display_name"]
@property
def region(self):
return self._raw["metadata"]["OS-EXT-AZ:availability_zone"]
class FloatingIP(BaseModelConstruct):
relevant_meters = ["ip.floating"]
usage_strategies = {"duration": {"usage": "duration", "service": "type"}}
type = "floating_ip" # object storage
@property
def duration(self):
# How much use this had.
return Decimal(self.usage()["ip.floating"].volume())
# Size is a gauge measured every 10 minutes.
# So that needs to be compressed to 60-minute intervals
class Object(BaseModelConstruct):
relevant_meters = ["storage.objects.size"]
usage_strategies = {"size": {"usage": "size", "service": "storage_size"}}
type = "object_storage" # object storage
@property
def size(self):
# How much use this had.
return Decimal(to_mb(self.usage()["storage.objects.size"].volume()))
# Size is a gauge measured every 10 minutes.
# So that needs to be compressed to 60-minute intervals
class Volume(BaseModelConstruct):
relevant_meters = ["volume.size"]
usage_strategies = {"size": {"usage": "size", "service": "volume_size"}}
type = "volume"
@property
def size(self):
# Size of the thing over time.
return Decimal(to_mb(self.usage()["volume.size"].volume()))
@property
def name(self):
return self._raw["metadata"]["display_name"]
class Network(BaseModelConstruct):
relevant_meters = ["network.outgoing.bytes", "network.incoming.bytes"]
usage_strategies = {"outgoing": {"usage": "outgoing",
"service": "outgoing_megabytes"},
"incoming": {"usage": "incoming",
"service": "incoming_megabytes"}}
type = "network_interface"
@property
def outgoing(self):
# Size of the thing over time.
return Decimal(to_mb(self.usage()["network.outgoing.bytes"].volume()))
@property
def incoming(self):
# Size of the thing over time.
return Decimal(to_mb(self.usage()["network.incoming.bytes"].volume()))