Add consumptions API support.
Change-Id: I56a60b98801fce9de6a792371d3ca60ed5712c56
This commit is contained in:
parent
ff26ed98e7
commit
711c54e6d2
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import routes
|
import routes
|
||||||
|
|
||||||
|
from bilean.api.openstack.v1 import consumptions
|
||||||
from bilean.api.openstack.v1 import events
|
from bilean.api.openstack.v1 import events
|
||||||
from bilean.api.openstack.v1 import policies
|
from bilean.api.openstack.v1 import policies
|
||||||
from bilean.api.openstack.v1 import resources
|
from bilean.api.openstack.v1 import resources
|
||||||
@ -172,4 +173,21 @@ class API(wsgi.Router):
|
|||||||
action="index",
|
action="index",
|
||||||
conditions={'method': 'GET'})
|
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)
|
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)
|
project_safe=project_safe)
|
||||||
|
|
||||||
|
|
||||||
def consumption_get_all(context, limit=None, marker=None, sort_keys=None,
|
def consumption_get_all(context, user_id=None, limit=None, marker=None,
|
||||||
sort_dir=None, filters=None, project_safe=True):
|
sort_keys=None, sort_dir=None, filters=None,
|
||||||
return IMPL.consumption_get_all(context, limit=limit,
|
project_safe=True):
|
||||||
|
return IMPL.consumption_get_all(context,
|
||||||
|
user_id=user_id,
|
||||||
|
limit=limit,
|
||||||
marker=marker,
|
marker=marker,
|
||||||
sort_keys=sort_keys,
|
sort_keys=sort_keys,
|
||||||
sort_dir=sort_dir,
|
sort_dir=sort_dir,
|
||||||
|
@ -881,14 +881,17 @@ def consumption_get(context, consumption_id, project_safe=True):
|
|||||||
return consumption
|
return consumption
|
||||||
|
|
||||||
|
|
||||||
def consumption_get_all(context, limit=None, marker=None, sort_keys=None,
|
def consumption_get_all(context, user_id=None, limit=None, marker=None,
|
||||||
sort_dir=None, filters=None, project_safe=True):
|
sort_keys=None, sort_dir=None, filters=None,
|
||||||
|
project_safe=True):
|
||||||
query = model_query(context, models.Consumption)
|
query = model_query(context, models.Consumption)
|
||||||
|
|
||||||
if context.is_admin:
|
if context.is_admin:
|
||||||
project_safe = False
|
project_safe = False
|
||||||
if project_safe:
|
if project_safe:
|
||||||
query = query.filter_by(user_id=context.project)
|
query = query.filter_by(user_id=context.project)
|
||||||
|
elif user_id:
|
||||||
|
query = query.filter_by(user_id=user_id)
|
||||||
if filters is None:
|
if filters is None:
|
||||||
filters = {}
|
filters = {}
|
||||||
|
|
||||||
|
@ -67,11 +67,14 @@ class Consumption(object):
|
|||||||
return cls.from_db_record(record)
|
return cls.from_db_record(record)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_all(cls, context, limit=None, marker=None, sort_keys=None,
|
def load_all(cls, context, user_id=None, limit=None, marker=None,
|
||||||
sort_dir=None, filters=None, project_safe=True):
|
sort_keys=None, sort_dir=None, filters=None,
|
||||||
|
project_safe=True):
|
||||||
'''Retrieve all consumptions from database.'''
|
'''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,
|
marker=marker,
|
||||||
filters=filters,
|
filters=filters,
|
||||||
sort_keys=sort_keys,
|
sort_keys=sort_keys,
|
||||||
|
@ -34,6 +34,7 @@ from bilean.common import schema
|
|||||||
from bilean.common import utils
|
from bilean.common import utils
|
||||||
from bilean.db import api as db_api
|
from bilean.db import api as db_api
|
||||||
from bilean.engine.actions import base as action_mod
|
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 dispatcher
|
||||||
from bilean.engine import environment
|
from bilean.engine import environment
|
||||||
from bilean.engine import event as event_mod
|
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)
|
self.TG.start_action(self.engine_id, action_id=action_id)
|
||||||
|
|
||||||
LOG.info(_LI('User settle_account action queued: %s'), 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',
|
return self.call(ctxt, self.make_msg('settle_account',
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
task=task))
|
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