
udating the api to be able to return salesorders between a given range, as well as the client/shell to make use of this. Has resulted in a lot of duplicate code, but next patch will go through and clean up a bunch of that, and extract a few validators into either decorators, or at least helper functions. Change-Id: I59ed58c32b8dd4a75babf70df188e965e5e94a16
111 lines
4.2 KiB
Python
111 lines
4.2 KiB
Python
from sqlalchemy import func
|
|
from .models import Resource, UsageEntry, Tenant, SalesOrder
|
|
import json
|
|
import config
|
|
|
|
|
|
class Database(object):
|
|
|
|
def __init__(self, session):
|
|
self.session = session
|
|
|
|
def insert_tenant(self, tenant_id, tenant_name, metadata, timestamp):
|
|
"""If a tenant exists does nothing,
|
|
and if it doesn't, creates and inserts it."""
|
|
# Have we seen this tenant before?
|
|
query = self.session.query(Tenant).\
|
|
filter(Tenant.id == tenant_id)
|
|
if query.count() == 0:
|
|
tenant = Tenant(id=tenant_id,
|
|
info=metadata,
|
|
name=tenant_name,
|
|
created=timestamp
|
|
)
|
|
self.session.add(tenant)
|
|
self.session.flush() # can't assume deferred constraints.
|
|
return tenant
|
|
else:
|
|
return query[0]
|
|
|
|
def insert_resource(self, tenant_id, resource_id, resource_type,
|
|
timestamp, entry):
|
|
query = self.session.query(Resource).\
|
|
filter(Resource.id == resource_id,
|
|
Resource.tenant_id == tenant_id)
|
|
if query.count() == 0:
|
|
info = self.merge_resource_metadata({'type': resource_type}, entry)
|
|
self.session.add(Resource(
|
|
id=resource_id,
|
|
info=json.dumps(info),
|
|
tenant_id=tenant_id,
|
|
created=timestamp))
|
|
self.session.flush() # can't assume deferred constraints.
|
|
else:
|
|
md_dict = json.loads(query[0].info)
|
|
md_dict = self.merge_resource_metadata(md_dict, entry)
|
|
query[0].info = json.dumps(md_dict)
|
|
|
|
def insert_usage(self, tenant_id, resource_id, entries, unit,
|
|
start, end, timestamp):
|
|
for service, volume in entries.items():
|
|
entry = UsageEntry(
|
|
service=service,
|
|
volume=volume,
|
|
unit=unit,
|
|
resource_id=resource_id,
|
|
tenant_id=tenant_id,
|
|
start=start,
|
|
end=end,
|
|
created=timestamp)
|
|
self.session.add(entry)
|
|
print entry
|
|
|
|
def enter(self, tenant, resource, entries, timestamp):
|
|
"""Creates a new database entry for every usage strategy
|
|
in a resource, for all the resources given"""
|
|
raise Exception("Dead!")
|
|
|
|
def usage(self, start, end, tenant_id):
|
|
"""Returns a query of usage entries for a given tenant,
|
|
in the given range.
|
|
start, end: define the range to query
|
|
tenant: a tenant entry (tenant_id for now)"""
|
|
|
|
# build a query set in the format:
|
|
# tenant_id | resource_id | service | sum(volume)
|
|
query = self.session.query(UsageEntry.tenant_id,
|
|
UsageEntry.resource_id,
|
|
UsageEntry.service,
|
|
UsageEntry.unit,
|
|
func.sum(UsageEntry.volume).label("volume")).\
|
|
filter(UsageEntry.start >= start, UsageEntry.end <= end).\
|
|
filter(UsageEntry.tenant_id == tenant_id).\
|
|
group_by(UsageEntry.tenant_id, UsageEntry.resource_id,
|
|
UsageEntry.service, UsageEntry.unit)
|
|
|
|
return query
|
|
|
|
def get_resource_metadata(self, resource_id):
|
|
info = self.session.query(Resource.info).\
|
|
filter(Resource.id == resource_id)
|
|
return json.loads(info[0].info)
|
|
|
|
def get_sales_orders(self, tenant_id, start, end):
|
|
query = self.session.query(SalesOrder).\
|
|
filter(SalesOrder.start <= end, SalesOrder.end >= start).\
|
|
filter(SalesOrder.tenant_id == tenant_id)
|
|
return query
|
|
|
|
def merge_resource_metadata(self, md_dict, entry):
|
|
fields = config.collection['metadata_def'].get(md_dict['type'], {})
|
|
for field, sources in fields.iteritems():
|
|
for i, source in enumerate(sources):
|
|
try:
|
|
md_dict[field] = entry['resource_metadata'][sources[0]]
|
|
break
|
|
except KeyError:
|
|
# Just means we haven't found the right value yet.
|
|
pass
|
|
|
|
return md_dict
|