various fixes to make usage collection work

Change-Id: I037bd6d4dfa481ec58314d396ded2307e93ec614
This commit is contained in:
Chris Forbes 2014-04-04 15:53:50 +13:00
parent e8aabf28c7
commit 4f0ee5f682
8 changed files with 60 additions and 71 deletions

View File

@ -102,11 +102,11 @@ def keystone(func):
def collect_usage(tenant, db, session, resp, end): def collect_usage(tenant, db, session, resp, end):
timestamp = datetime.now() timestamp = datetime.now()
db.insert_tenant(tenant.conn['id'], tenant.conn['name'], db.insert_tenant(tenant.id, tenant.name,
tenant.conn['description'], timestamp) tenant.description, timestamp)
session.begin(subtransactions=True) session.begin(subtransactions=True)
start = session.query(func.max(UsageEntry.end).label('end')).\ start = session.query(func.max(UsageEntry.end).label('end')).\
filter(UsageEntry.tenant_id == tenant.conn['id']).first().end filter(UsageEntry.tenant_id == tenant.id).first().end
if not start: if not start:
start = datetime.strptime(dawn_of_time, iso_date) start = datetime.strptime(dawn_of_time, iso_date)
@ -118,7 +118,7 @@ def collect_usage(tenant, db, session, resp, end):
try: try:
session.commit() session.commit()
resp["tenants"].append( resp["tenants"].append(
{"id": tenant.conn['id'], {"id": tenant.id,
"updated": True, "updated": True,
"start": start.strftime(iso_time), "start": start.strftime(iso_time),
"end": end.strftime(iso_time) "end": end.strftime(iso_time)
@ -127,7 +127,7 @@ def collect_usage(tenant, db, session, resp, end):
except sqlalchemy.exc.IntegrityError: except sqlalchemy.exc.IntegrityError:
# this is fine. # this is fine.
resp["tenants"].append( resp["tenants"].append(
{"id": tenant.conn['id'], {"id": tenant.id,
"updated": False, "updated": False,
"error": "Integrity error", "error": "Integrity error",
"start": start.strftime(iso_time), "start": start.strftime(iso_time),
@ -146,24 +146,30 @@ def run_usage_collection():
The volume will be parsed from JSON as a Decimal object. The volume will be parsed from JSON as a Decimal object.
""" """
try:
session = Session() session = Session()
artifice = interface.Artifice() artifice = interface.Artifice()
db = database.Database(session) db = database.Database(session)
tenants = artifice.tenants tenants = artifice.tenants
end = datetime.now().\ end = datetime.now().\
replace(minute=0, second=0, microsecond=0) replace(minute=0, second=0, microsecond=0)
resp = {"tenants": [], "errors": 0} resp = {"tenants": [], "errors": 0}
for tenant in tenants: for tenant in tenants:
collect_usage(tenant, db, session, resp, end) collect_usage(tenant, db, session, resp, end)
session.close() session.close()
return json.dumps(resp) return json.dumps(resp)
except Exception as e:
print 'Exception escaped!', type(e), e
import traceback
traceback.print_exc()
def generate_sales_order(tenant, session, end, rates): def generate_sales_order(tenant, session, end, rates):

View File

@ -53,6 +53,7 @@ class Database(object):
end=end, end=end,
created=timestamp created=timestamp
) )
print entry
self.session.add(entry) self.session.add(entry)
self.session.flush() self.session.flush()
except TransformerValidationError: except TransformerValidationError:

View File

@ -1,12 +1,19 @@
from novaclient.v1_1 import client from novaclient.v1_1 import client
import config import config
cache = {}
def flavor_name(f_id): def flavor_name(f_id):
nova = client.Client( f_id = int(f_id)
config.auth['username'],
config.auth['password'], if f_id not in cache:
config.auth['default_tenant'], nova = client.Client(
config.auth['end_point'], config.auth['username'],
service_type="compute") config.auth['password'],
return nova.flavors.get(f_id).name config.auth['default_tenant'],
config.auth['end_point'],
service_type="compute",
insecure=config.auth['insecure'])
cache[f_id] = nova.flavors.get(f_id).name
return cache[f_id]

View File

@ -76,20 +76,15 @@ class Tenant(object):
self._meters = set() self._meters = set()
self._resources = None self._resources = None
def __getitem__(self, item): @property
def id(self):
try: return self.tenant.id
return getattr(self.tenant, item) @property
except AttributeError: def name(self):
try: return self.tenant.name
return self.tenant[item] @property
except KeyError: def description(self):
raise KeyError("No such key '%s' in tenant" % item) return self.tenant.description
def __getattr__(self, attr):
if attr not in self.tenant:
return object.__getattribute__(self, attr)
return self.tenant[attr]
def resources(self, start, end): def resources(self, start, end):
if not self._resources: if not self._resources:

View File

@ -1,5 +1,6 @@
import requests import requests
from requests.exceptions import ConnectionError from requests.exceptions import ConnectionError
import json
class Client(object): class Client(object):
@ -9,20 +10,20 @@ class Client(object):
self.auth_token = kwargs.get('token') self.auth_token = kwargs.get('token')
def usage(self, tenants): def usage(self, tenants):
url = self.endpoint + "usage" url = self.endpoint + "collect_usage"
data = {"tenants": tenants} data = {"tenants": tenants}
try: try:
response = requests.post(url, response = requests.post(url,
headers={"Content-Type": headers={"Content-Type":
"application/json", "application/json",
"token": self.auth_token}, "token": self.auth_token},
data=data) data=json.dumps(data))
if response.status_code != 200: if response.status_code != 200:
raise AttributeError("Usage cycle failed: " + response.text + raise AttributeError("Usage cycle failed: " + response.text +
" code: " + str(response.status_code)) " code: " + str(response.status_code))
except ConnectionError: except ConnectionError as e:
pass print e
def sales_order(self, tenants): def sales_order(self, tenants):
url = self.endpoint + "sales_order" url = self.endpoint + "sales_order"
@ -37,5 +38,5 @@ class Client(object):
raise AttributeError("Sales order cycle failed: " + raise AttributeError("Sales order cycle failed: " +
response.text + " code: " + response.text + " code: " +
str(response.status_code)) str(response.status_code))
except ConnectionError: except ConnectionError as e:
pass print e

View File

@ -62,7 +62,7 @@ if __name__ == '__main__':
args = parser.parse_args() args = parser.parse_args()
conf = {'api': {'endpoint': 'http://0.0.0.0/', conf = {'api': {'endpoint': 'http://0.0.0.0:8000/',
'token': 'sah324sdf5wad4dh839uhjuUH'}} 'token': 'sah324sdf5wad4dh839uhjuUH'}}
# try: # try:

View File

@ -1,25 +0,0 @@
import sys, os
loc = None
try:
loc, fn = os.path.split(__file__)
except NameError:
loc = os.getcwd()
sys.path.insert(0, os.path.abspath(os.path.join(loc +"/../artifice")))
from models import usage, resources, tenants, Session, Base
# string = 'postgresql://%(username)s:%(password)s@%(host)s:%(port)s/%(database)s'
# conn_string = string % {'username':'aurynn', 'host':'localhost', 'port':5433, 'password':'aurynn', 'database':'artifice'}
from sqlalchemy import MetaData, create_engine
import os
engine = create_engine( os.environ["DATABASE_URL"] )
Session.configure(bind=engine)
s = Session()
Base.metadata.create_all(engine)

View File

@ -30,7 +30,11 @@ class TestApi(test_interface.TestInterface):
for tenant in constants.TENANTS: for tenant in constants.TENANTS:
t = mock.Mock(spec=interface.Tenant) t = mock.Mock(spec=interface.Tenant)
t.usage.return_value = usage t.usage.return_value = usage
t.conn = tenant t.conn = mock.Mock()
t.tenant = tenant
t.id = tenant['id']
t.name = tenant['name']
t.description = tenant['description']
tenants.append(t) tenants.append(t)
artifice = mock.Mock(spec=interface.Artifice) artifice = mock.Mock(spec=interface.Artifice)