Altered the csv formatting, and added reliance on clerk for rates collection.

This commit is contained in:
adriant 2014-02-17 09:43:14 +13:00
parent ede6e2ecf0
commit 2a4714fdad
6 changed files with 37 additions and 29 deletions

View File

@ -1,11 +1,12 @@
import os
from csv import writer
from artifice import invoice
from artifice import clerk_mixins
import yaml
from decimal import *
class Csv(invoice.RatesFileMixin, invoice.Invoice):
class Csv(clerk_mixins.ClerkRatesMixin, invoice.Invoice):
def __init__(self, tenant, start, end, config):
self.config = config
@ -19,26 +20,33 @@ class Csv(invoice.RatesFileMixin, invoice.Invoice):
def bill(self):
# Usage is one of VMs, Storage, or Volumes.
for element in self.tenant.resources.values():
appendee = []
print " * " + element.metadata['type']
print " - resource id: " + str(element.id)
appendee.append(element.id)
self.add_line(element.metadata['type'], [element.id])
appendee = []
appendee2 = []
for key, value in element.metadata.iteritems():
print " - " + key + ": " + str(value)
appendee.append(value)
appendee.append(key + str(":"))
appendee2.append(value)
self.add_line(element.metadata['type'], appendee)
self.add_line(element.metadata['type'], appendee2)
total_cost = Decimal(0.0)
appendee = ["", "service:", "usage:", "rate:", "cost:"]
appendee = ["service:", "usage:", "rate:", "cost:"]
self.add_line(element.metadata['type'], appendee)
for strategy in element.usage_strategies.values():
appendee = ["-"]
appendee = []
cost = Decimal(0.0)
usage = Decimal(strategy.volume)
rate = self.rate(strategy.service)
# GET REGION FROM CONFIG:
region = 'wellington'
rate = self.rate(strategy.service, region)
cost = usage * rate
total_cost += cost
appendee.append(strategy.service)
@ -47,11 +55,11 @@ class Csv(invoice.RatesFileMixin, invoice.Invoice):
appendee.append(round(cost, 2))
print " - " + strategy.service + ": " + str(usage)
print " - rate: " + str(rate)
print " - cost: " + str(cost)
print " - cost: " + str(round(cost))
self.add_line(element.metadata['type'], appendee)
appendee = ["total cost:", round(total_cost, 2)]
self.add_line(element.metadata['type'], appendee)
print " - total cost: " + str(total_cost)
print " - total cost: " + str(round(total_cost))
self.add_line(element.metadata['type'], [])
self.total += total_cost

View File

@ -1,6 +1,5 @@
import requests
from decimal import Decimal
from artifice import NotFound
class ClerkNamesMixin(object):
@ -14,14 +13,13 @@ class ClerkNamesMixin(object):
return str(response.json()['pretty_name'])
elif response.status_code == 404:
print "not found"
raise NotFound
class ClerkRatesMixin(object):
def rate(self, name, loc_name):
url = self.config["clerk"]["url"]
url = (url + "locations/" + loc_name +
url = "http://10.5.36.32/"
url = (url + "regions/" + loc_name +
"/services/" + name + "/rates/current/")
response = requests.get(url,
headers={"Content-Type": "application/json"})
@ -29,4 +27,3 @@ class ClerkRatesMixin(object):
return Decimal(response.json()['rate'])
elif response.status_code == 404:
print "not found"
raise NotFound

View File

@ -1,5 +1,4 @@
from sqlalchemy import func
from sqlalchemy.sql import exists
from .models.db_models import Tenant as tenant_model
from .models.db_models import UsageEntry, Resource
from .models import billing, Base
@ -40,13 +39,12 @@ class Database(object):
filter(Resource.resource_id == element.get("resource_id"))
if query.count() == 0:
el_type = element.type
if el_type != 'virtual_machine':
if el_type not in ('virtual_machine', 'volume'):
info = json.dumps({'type': el_type})
else:
info = json.dumps({'type': el_type,
'name': element.name})
# info should really be a json...
# but is just a dict cast to a str for now
self.session.add(Resource(resource_id=
element.get("resource_id"),
info=str(info)))
@ -90,8 +88,8 @@ class Database(object):
for entry in query:
# since there is no field for volume after the sum, we must
# access the entry by index
usage_strat = billing.UsageStrategy(entry.service,
Decimal(entry[3]))
volume = Decimal(entry[3])
usage_strat = billing.UsageStrategy(entry.service, volume)
# does this tenant exist yet?
if entry.tenant_id not in tenants_dict:

View File

@ -86,10 +86,10 @@ class VM(BaseModelConstruct):
# sometimes instance_type is needed instead....
try:
# print "\"flavor.name\" was used"
return self._raw["metadata"]["flavor.name"]
return self._raw["metadata"]["flavor.name"].replace(".", "_")
except KeyError:
# print "\"instance_type\" was used"
return self._raw["metadata"]["instance_type"]
return self._raw["metadata"]["instance_type"].replace(".", "_")
@property
def memory(self):
@ -157,6 +157,10 @@ class Volume(BaseModelConstruct):
# 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"]

View File

@ -64,22 +64,22 @@ class TestDatabaseModels(test_interface.TestInterface):
print " " + resource.id
if resource.id == "db8037b2-9f1c-4dd2-94dd-ea72f49a21d7":
strat = resource.usage_strategies["m1.nano"]
strat = resource.usage_strategies["m1_nano"]
self.assertEqual(strat.volume, 1)
if resource.id == "9a9e7c74-2a2f-4a30-bc75-fadcbc5f304a":
strat = resource.usage_strategies["m1.micro"]
strat = resource.usage_strategies["m1_micro"]
self.assertEqual(strat.volume, 1)
if resource.id == "0a57e3da-9e85-4690-8ba9-ee7573619ec3":
strat = resource.usage_strategies["m1.small"]
strat = resource.usage_strategies["m1_small"]
self.assertEqual(strat.volume, 1)
if resource.id == "388b3939-8854-4a1b-a133-e738f1ffbb0a":
strat = resource.usage_strategies["m1.micro"]
strat = resource.usage_strategies["m1_micro"]
self.assertEqual(strat.volume, 1)
if resource.id == "de35c688-5a82-4ce5-a7e0-36245d2448bc":
strat = resource.usage_strategies["m1.tiny"]
strat = resource.usage_strategies["m1_tiny"]
self.assertEqual(strat.volume, 1)
if resource.id == "e404920f-cfc8-40ba-bc53-a5c610714bd":
strat = resource.usage_strategies["m1.medium"]
strat = resource.usage_strategies["m1_medium"]
self.assertEqual(strat.volume, 0)
if resource.id == "3f7b702e4ca14cd99aebf4c4320e00ec":

View File

@ -11,7 +11,8 @@ Base = declarative_base()
config = {
"output_file": '%(tenant)s-%(start)s-%(end)s.csv',
"output_path": "./invoices",
"rates": {"file": "/home/adriant/Projects/openstack-artifice/examples/csv_rates.csv"}
"rates": {"file":
"/home/adriant/Projects/openstack-artifice/examples/csv_rates.csv"}
}