Add consumptions API support.
Change-Id: I56a60b98801fce9de6a792371d3ca60ed5712c56
This commit is contained in:
parent
ff26ed98e7
commit
711c54e6d2
@ -13,6 +13,7 @@
|
||||
|
||||
import routes
|
||||
|
||||
from bilean.api.openstack.v1 import consumptions
|
||||
from bilean.api.openstack.v1 import events
|
||||
from bilean.api.openstack.v1 import policies
|
||||
from bilean.api.openstack.v1 import resources
|
||||
@ -172,4 +173,21 @@ class API(wsgi.Router):
|
||||
action="index",
|
||||
conditions={'method': 'GET'})
|
||||
|
||||
# Consumptions
|
||||
cons_resource = consumptions.create_resource(conf)
|
||||
cons_path = "/consumptions"
|
||||
with mapper.submapper(controller=cons_resource,
|
||||
path_prefix=cons_path) as cons_mapper:
|
||||
|
||||
# Consumption collection
|
||||
cons_mapper.connect("consumption_index",
|
||||
"",
|
||||
action="index",
|
||||
conditions={'method': 'GET'})
|
||||
|
||||
cons_mapper.connect("consumption_statistics",
|
||||
"/statistics",
|
||||
action="statistics",
|
||||
conditions={'method': 'GET'})
|
||||
|
||||
super(API, self).__init__(mapper)
|
||||
|
88
bilean/api/openstack/v1/consumptions.py
Normal file
88
bilean/api/openstack/v1/consumptions.py
Normal file
@ -0,0 +1,88 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from bilean.api.openstack.v1 import util
|
||||
from bilean.common import consts
|
||||
from bilean.common import serializers
|
||||
from bilean.common import utils
|
||||
from bilean.common import wsgi
|
||||
from bilean.rpc import client as rpc_client
|
||||
|
||||
|
||||
class ConsumptionController(object):
|
||||
"""WSGI controller for Consumptions in Bilean v1 API."""
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'consumptions'
|
||||
|
||||
def __init__(self, options):
|
||||
self.options = options
|
||||
self.rpc_client = rpc_client.EngineClient()
|
||||
|
||||
@util.policy_enforce
|
||||
def index(self, req):
|
||||
"""Lists all consumptions."""
|
||||
filter_whitelist = {
|
||||
'resource_type': 'mixed',
|
||||
}
|
||||
param_whitelist = {
|
||||
'user_id': 'single',
|
||||
'start_time': 'single',
|
||||
'end_time': 'single',
|
||||
'limit': 'single',
|
||||
'marker': 'single',
|
||||
'sort_dir': 'single',
|
||||
'sort_keys': 'multi',
|
||||
}
|
||||
params = util.get_allowed_params(req.params, param_whitelist)
|
||||
filters = util.get_allowed_params(req.params, filter_whitelist)
|
||||
|
||||
key = consts.PARAM_LIMIT
|
||||
if key in params:
|
||||
params[key] = utils.parse_int_param(key, params[key])
|
||||
|
||||
if not filters:
|
||||
filters = None
|
||||
consumptions = self.rpc_client.consumption_list(req.context,
|
||||
filters=filters,
|
||||
**params)
|
||||
|
||||
return {'consumptions': consumptions}
|
||||
|
||||
@util.policy_enforce
|
||||
def statistics(self, req):
|
||||
'''Consumptions statistics.'''
|
||||
filter_whitelist = {
|
||||
'resource_type': 'mixed',
|
||||
}
|
||||
param_whitelist = {
|
||||
'user_id': 'single',
|
||||
'start_time': 'single',
|
||||
'end_time': 'single',
|
||||
}
|
||||
params = util.get_allowed_params(req.params, param_whitelist)
|
||||
filters = util.get_allowed_params(req.params, filter_whitelist)
|
||||
|
||||
if not filters:
|
||||
filters = None
|
||||
statistics = self.rpc_client.consumption_statistics(req.context,
|
||||
filters=filters,
|
||||
**params)
|
||||
|
||||
return {'statistics': statistics}
|
||||
|
||||
|
||||
def create_resource(ops):
|
||||
"""Consumption resource factory method."""
|
||||
deserializer = wsgi.JSONRequestDeserializer()
|
||||
serializer = serializers.JSONResponseSerializer()
|
||||
return wsgi.Resource(ConsumptionController(ops), deserializer, serializer)
|
@ -312,9 +312,12 @@ def consumption_get(context, consumption_id, project_safe=True):
|
||||
project_safe=project_safe)
|
||||
|
||||
|
||||
def consumption_get_all(context, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, project_safe=True):
|
||||
return IMPL.consumption_get_all(context, limit=limit,
|
||||
def consumption_get_all(context, user_id=None, limit=None, marker=None,
|
||||
sort_keys=None, sort_dir=None, filters=None,
|
||||
project_safe=True):
|
||||
return IMPL.consumption_get_all(context,
|
||||
user_id=user_id,
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
sort_keys=sort_keys,
|
||||
sort_dir=sort_dir,
|
||||
|
@ -881,14 +881,17 @@ def consumption_get(context, consumption_id, project_safe=True):
|
||||
return consumption
|
||||
|
||||
|
||||
def consumption_get_all(context, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, project_safe=True):
|
||||
def consumption_get_all(context, user_id=None, limit=None, marker=None,
|
||||
sort_keys=None, sort_dir=None, filters=None,
|
||||
project_safe=True):
|
||||
query = model_query(context, models.Consumption)
|
||||
|
||||
if context.is_admin:
|
||||
project_safe = False
|
||||
if project_safe:
|
||||
query = query.filter_by(user_id=context.project)
|
||||
elif user_id:
|
||||
query = query.filter_by(user_id=user_id)
|
||||
if filters is None:
|
||||
filters = {}
|
||||
|
||||
|
@ -67,11 +67,14 @@ class Consumption(object):
|
||||
return cls.from_db_record(record)
|
||||
|
||||
@classmethod
|
||||
def load_all(cls, context, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, project_safe=True):
|
||||
def load_all(cls, context, user_id=None, limit=None, marker=None,
|
||||
sort_keys=None, sort_dir=None, filters=None,
|
||||
project_safe=True):
|
||||
'''Retrieve all consumptions from database.'''
|
||||
|
||||
records = db_api.consumption_get_all(context, limit=limit,
|
||||
records = db_api.consumption_get_all(context,
|
||||
user_id=user_id,
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
filters=filters,
|
||||
sort_keys=sort_keys,
|
||||
|
@ -34,6 +34,7 @@ from bilean.common import schema
|
||||
from bilean.common import utils
|
||||
from bilean.db import api as db_api
|
||||
from bilean.engine.actions import base as action_mod
|
||||
from bilean.engine import consumption as cons_mod
|
||||
from bilean.engine import dispatcher
|
||||
from bilean.engine import environment
|
||||
from bilean.engine import event as event_mod
|
||||
@ -679,3 +680,71 @@ class EngineService(service.Service):
|
||||
self.TG.start_action(self.engine_id, action_id=action_id)
|
||||
|
||||
LOG.info(_LI('User settle_account action queued: %s'), action_id)
|
||||
|
||||
@request_context
|
||||
def consumption_list(self, cnxt, user_id=None, limit=None,
|
||||
marker=None, sort_keys=None, sort_dir=None,
|
||||
filters=None, project_safe=True):
|
||||
if limit is not None:
|
||||
limit = utils.parse_int_param('limit', limit)
|
||||
|
||||
consumptions = cons_mod.Consumption.load_all(cnxt,
|
||||
user_id=user_id,
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
sort_keys=sort_keys,
|
||||
sort_dir=sort_dir,
|
||||
filters=filters,
|
||||
project_safe=project_safe)
|
||||
return [c.to_dict() for c in consumptions]
|
||||
|
||||
@request_context
|
||||
def consumption_statistics(self, cnxt, user_id=None, filters=None,
|
||||
start_time=None, end_time=None,
|
||||
project_safe=True):
|
||||
result = {}
|
||||
if start_time is None:
|
||||
start_time = 0
|
||||
else:
|
||||
start_time = utils.format_time_to_seconds(start_time)
|
||||
start_time = utils.make_decimal(start_time)
|
||||
|
||||
now_time = utils.format_time_to_seconds(timeutils.utcnow())
|
||||
now_time = utils.make_decimal(now_time)
|
||||
if end_time is None:
|
||||
end_time = now_time
|
||||
else:
|
||||
end_time = utils.format_time_to_seconds(end_time)
|
||||
end_time = utils.make_decimal(end_time)
|
||||
|
||||
consumptions = cons_mod.Consumption.load_all(cnxt, user_id=user_id,
|
||||
project_safe=project_safe)
|
||||
for cons in consumptions:
|
||||
if cons.start_time > end_time or cons.end_time < start_time:
|
||||
continue
|
||||
et = min(cons.end_time, end_time)
|
||||
st = max(cons.start_time, start_time)
|
||||
seconds = et - st
|
||||
cost = cons.rate * seconds
|
||||
if cons.resource_type not in result:
|
||||
result[cons.resource_type] = cost
|
||||
else:
|
||||
result[cons.resource_type] += cost
|
||||
|
||||
resources = plugin_base.Resource.load_all(cnxt, user_id=user_id,
|
||||
project_safe=project_safe)
|
||||
for res in resources:
|
||||
if res.last_bill > end_time or now_time < start_time:
|
||||
continue
|
||||
et = min(now_time, end_time)
|
||||
st = max(res.last_bill, start_time)
|
||||
seconds = et - st
|
||||
cost = res.rate * seconds
|
||||
if res.resource_type not in result:
|
||||
result[res.resource_type] = cost
|
||||
else:
|
||||
result[res.resource_type] += cost
|
||||
|
||||
for key in six.iterkeys(result):
|
||||
result[key] = utils.dec2str(result[key])
|
||||
return result
|
||||
|
@ -210,3 +210,25 @@ class EngineClient(object):
|
||||
return self.call(ctxt, self.make_msg('settle_account',
|
||||
user_id=user_id,
|
||||
task=task))
|
||||
|
||||
# consumptions
|
||||
def consumption_list(self, ctxt, user_id=None, limit=None, marker=None,
|
||||
sort_keys=None, sort_dir=None, filters=None,
|
||||
project_safe=True):
|
||||
return self.call(ctxt, self.make_msg('consumption_list',
|
||||
user_id=user_id,
|
||||
limit=limit, marker=marker,
|
||||
sort_keys=sort_keys,
|
||||
sort_dir=sort_dir,
|
||||
filters=filters,
|
||||
project_safe=project_safe))
|
||||
|
||||
def consumption_statistics(self, ctxt, user_id=None, filters=None,
|
||||
start_time=None, end_time=None,
|
||||
project_safe=True):
|
||||
return self.call(ctxt, self.make_msg('consumption_statistics',
|
||||
user_id=user_id,
|
||||
filters=filters,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
project_safe=project_safe))
|
||||
|
Loading…
Reference in New Issue
Block a user