Added support for total on API
Added a generic function to load storage backend Added storage hooks to API Added total calculation on backends Moved NoTimeFrame exception to base code Change-Id: I917335aaeb01b58c1cbb86ae63b260d3f91a7ba7
This commit is contained in:
parent
f41fd4c6d7
commit
734c2fae8d
|
@ -28,6 +28,7 @@ from cloudkitty.api import hooks
|
|||
from cloudkitty.common import rpc
|
||||
from cloudkitty import config # noqa
|
||||
from cloudkitty.openstack.common import log as logging
|
||||
from cloudkitty import storage
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -70,8 +71,11 @@ def setup_app(pecan_config=None, extra_hooks=None):
|
|||
|
||||
client = rpc.get_client(target)
|
||||
|
||||
storage_backend = storage.get_storage()
|
||||
|
||||
app_hooks = [
|
||||
hooks.RPCHook(client)
|
||||
hooks.RPCHook(client),
|
||||
hooks.StorageHook(storage_backend),
|
||||
]
|
||||
|
||||
return pecan.make_app(
|
||||
|
|
|
@ -250,8 +250,12 @@ class ReportController(rest.RestController):
|
|||
"""Return the amount to pay for the current month.
|
||||
|
||||
"""
|
||||
# TODO(sheeprine): Get current total from DB
|
||||
return 10.0
|
||||
storage = pecan.request.storage_backend
|
||||
# FIXME(sheeprine): We should filter on user id.
|
||||
# Use keystone token information by default but make it overridable and
|
||||
# enforce it by policy engine
|
||||
total = storage.get_total()
|
||||
return total
|
||||
|
||||
|
||||
class V1Controller(rest.RestController):
|
||||
|
|
|
@ -24,3 +24,11 @@ class RPCHook(hooks.PecanHook):
|
|||
|
||||
def before(self, state):
|
||||
state.request.rpc_client = self._rpc_client
|
||||
|
||||
|
||||
class StorageHook(hooks.PecanHook):
|
||||
def __init__(self, storage_backend):
|
||||
self._storage_backend = storage_backend
|
||||
|
||||
def before(self, state):
|
||||
state.request.storage_backend = self._storage_backend
|
||||
|
|
|
@ -20,8 +20,9 @@ import datetime
|
|||
|
||||
from oslo.config import cfg
|
||||
import six
|
||||
from stevedore import driver
|
||||
|
||||
|
||||
STORAGES_NAMESPACE = 'cloudkitty.storage.backends'
|
||||
storage_opts = [
|
||||
cfg.StrOpt('backend',
|
||||
default='sqlalchemy',
|
||||
|
@ -31,6 +32,25 @@ storage_opts = [
|
|||
cfg.CONF.register_opts(storage_opts, group='storage')
|
||||
|
||||
|
||||
def get_storage():
|
||||
cfg.CONF.import_opt('period', 'cloudkitty.config', 'collect')
|
||||
storage_args = {'period': cfg.CONF.collect.period}
|
||||
backend = driver.DriverManager(
|
||||
STORAGES_NAMESPACE,
|
||||
cfg.CONF.storage.backend,
|
||||
invoke_on_load=True,
|
||||
invoke_kwds=storage_args).driver
|
||||
return backend
|
||||
|
||||
|
||||
class NoTimeFrame(Exception):
|
||||
"""Raised when there is no time frame available."""
|
||||
|
||||
def __init__(self):
|
||||
super(NoTimeFrame, self).__init__(
|
||||
"No time frame available")
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class BaseStorage(object):
|
||||
"""Base Storage class:
|
||||
|
@ -103,7 +123,9 @@ class BaseStorage(object):
|
|||
|
||||
@abc.abstractmethod
|
||||
def get_total(self):
|
||||
pass
|
||||
"""Return the current total.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_time_frame(self, begin, end, **filters):
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
#
|
||||
# @author: Stéphane Albert
|
||||
#
|
||||
import datetime
|
||||
import json
|
||||
|
||||
from oslo.db.sqlalchemy import utils
|
||||
import sqlalchemy
|
||||
|
||||
from cloudkitty import db
|
||||
from cloudkitty import storage
|
||||
|
@ -26,14 +28,6 @@ from cloudkitty.storage.sqlalchemy import models
|
|||
from cloudkitty import utils as ck_utils
|
||||
|
||||
|
||||
class NoTimeFrame(Exception):
|
||||
"""Raised when there is no time frame available."""
|
||||
|
||||
def __init__(self):
|
||||
super(NoTimeFrame, self).__init__(
|
||||
"No time frame available")
|
||||
|
||||
|
||||
class SQLAlchemyStorage(storage.BaseStorage):
|
||||
"""SQLAlchemy Storage Backend
|
||||
|
||||
|
@ -73,7 +67,20 @@ class SQLAlchemyStorage(storage.BaseStorage):
|
|||
return ck_utils.dt2ts(r.begin)
|
||||
|
||||
def get_total(self):
|
||||
pass
|
||||
model = models.RatedDataFrame
|
||||
|
||||
# Boundary calculation
|
||||
month_start = ck_utils.get_this_month()
|
||||
month_end = ck_utils.get_next_month()
|
||||
|
||||
session = db.get_session()
|
||||
rate = session.query(
|
||||
sqlalchemy.func.sum(model.rate).label('rate')
|
||||
).filter(
|
||||
model.begin >= month_start,
|
||||
model.end <= month_end
|
||||
).scalar()
|
||||
return rate
|
||||
|
||||
def get_time_frame(self, begin, end, **filters):
|
||||
"""Return a list of time frames.
|
||||
|
@ -89,14 +96,15 @@ class SQLAlchemyStorage(storage.BaseStorage):
|
|||
model,
|
||||
session
|
||||
).filter(
|
||||
model.begin >= begin,
|
||||
model.end <= end
|
||||
model.begin >= datetime.datetime.fromtimestamp(begin),
|
||||
model.end <= datetime.datetime.fromtimestamp(end)
|
||||
)
|
||||
for cur_filter in filters:
|
||||
q = q.filter(getattr(model, cur_filter) == filters[cur_filter])
|
||||
if not q:
|
||||
raise NoTimeFrame()
|
||||
return q.to_cloudkitty()
|
||||
r = q.all()
|
||||
if not r:
|
||||
raise storage.NoTimeFrame()
|
||||
return [entry.to_cloudkitty() for entry in r]
|
||||
|
||||
def _append_time_frame(self, res_type, frame):
|
||||
vol_dict = frame['vol']
|
||||
|
|
Loading…
Reference in New Issue