Simple tenant usage pagination
Stitches back together all the pages for the os-simple-tenant-usage call, so that the usage statistics are complete. Implements blueprint paginate-simple-tenant-usage Depends-on: If99db6933de012b71cf2c982075f08b3e664361e Change-Id: I8c1206807f707ef47dd92e3cb663970804e3ec8e
This commit is contained in:
parent
ab0efc05ab
commit
107bd083ef
@ -20,6 +20,7 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import collections
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
@ -27,6 +28,7 @@ from django.utils.functional import cached_property # noqa
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import six
|
||||
|
||||
from novaclient import api_versions
|
||||
from novaclient import client as nova_client
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from novaclient.v2.contrib import instance_action as nova_instance_action
|
||||
@ -866,15 +868,72 @@ def default_quota_update(request, **kwargs):
|
||||
novaclient(request).quota_classes.update(DEFAULT_QUOTA_NAME, **kwargs)
|
||||
|
||||
|
||||
def _get_usage_marker(usage):
|
||||
marker = None
|
||||
if hasattr(usage, 'server_usages') and usage.server_usages:
|
||||
marker = usage.server_usages[-1].get('instance_id')
|
||||
return marker
|
||||
|
||||
|
||||
def _get_usage_list_marker(usage_list):
|
||||
marker = None
|
||||
if usage_list:
|
||||
marker = _get_usage_marker(usage_list[-1])
|
||||
return marker
|
||||
|
||||
|
||||
def _merge_usage(usage, next_usage):
|
||||
usage.server_usages.extend(next_usage.server_usages)
|
||||
usage.total_hours += next_usage.total_hours
|
||||
usage.total_memory_mb_usage += next_usage.total_memory_mb_usage
|
||||
usage.total_vcpus_usage += next_usage.total_vcpus_usage
|
||||
usage.total_local_gb_usage += next_usage.total_local_gb_usage
|
||||
|
||||
|
||||
def _merge_usage_list(usages, next_usage_list):
|
||||
for next_usage in next_usage_list:
|
||||
if next_usage.tenant_id in usages:
|
||||
_merge_usage(usages[next_usage.tenant_id], next_usage)
|
||||
else:
|
||||
usages[next_usage.tenant_id] = next_usage
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def usage_get(request, tenant_id, start, end):
|
||||
return NovaUsage(novaclient(request).usage.get(tenant_id, start, end))
|
||||
client = novaclient(request)
|
||||
usage = client.usage.get(tenant_id, start, end)
|
||||
if client.api_version >= api_versions.APIVersion('2.40'):
|
||||
# If the number of instances used to calculate the usage is greater
|
||||
# than max_limit, the usage will be split across multiple requests
|
||||
# and the responses will need to be merged back together.
|
||||
marker = _get_usage_marker(usage)
|
||||
while marker:
|
||||
next_usage = client.usage.get(tenant_id, start, end, marker=marker)
|
||||
marker = _get_usage_marker(next_usage)
|
||||
if marker:
|
||||
_merge_usage(usage, next_usage)
|
||||
return NovaUsage(usage)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def usage_list(request, start, end):
|
||||
return [NovaUsage(u) for u in
|
||||
novaclient(request).usage.list(start, end, True)]
|
||||
client = novaclient(request)
|
||||
usage_list = client.usage.list(start, end, True)
|
||||
if client.api_version >= api_versions.APIVersion('2.40'):
|
||||
# If the number of instances used to calculate the usage is greater
|
||||
# than max_limit, the usage will be split across multiple requests
|
||||
# and the responses will need to be merged back together.
|
||||
usages = collections.OrderedDict()
|
||||
_merge_usage_list(usages, usage_list)
|
||||
marker = _get_usage_list_marker(usage_list)
|
||||
while marker:
|
||||
next_usage_list = client.usage.list(start, end, True,
|
||||
marker=marker)
|
||||
marker = _get_usage_list_marker(next_usage_list)
|
||||
if marker:
|
||||
_merge_usage_list(usages, next_usage_list)
|
||||
usage_list = usages.values()
|
||||
return [NovaUsage(u) for u in usage_list]
|
||||
|
||||
|
||||
@profiler.trace
|
||||
|
@ -24,6 +24,7 @@ from django import http
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from mox3.mox import IsA # noqa
|
||||
from novaclient import api_versions
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from novaclient.v2 import flavor_access as nova_flavor_access
|
||||
from novaclient.v2 import servers
|
||||
@ -201,6 +202,24 @@ class ComputeApiTests(test.APITestCase):
|
||||
'start', 'end')
|
||||
self.assertIsInstance(ret_val, api.nova.NovaUsage)
|
||||
|
||||
def test_usage_get_paginated(self):
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.api_version = api_versions.APIVersion('2.40')
|
||||
novaclient.usage = self.mox.CreateMockAnything()
|
||||
novaclient.usage.get(self.tenant.id, 'start', 'end')\
|
||||
.AndReturn(self.usages.first())
|
||||
novaclient.usage.get(
|
||||
self.tenant.id,
|
||||
'start',
|
||||
'end',
|
||||
marker=u'063cf7f3-ded1-4297-bc4c-31eae876cc93',
|
||||
).AndReturn({})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.nova.usage_get(self.request, self.tenant.id,
|
||||
'start', 'end')
|
||||
self.assertIsInstance(ret_val, api.nova.NovaUsage)
|
||||
|
||||
def test_usage_list(self):
|
||||
usages = self.usages.list()
|
||||
|
||||
@ -213,6 +232,25 @@ class ComputeApiTests(test.APITestCase):
|
||||
for usage in ret_val:
|
||||
self.assertIsInstance(usage, api.nova.NovaUsage)
|
||||
|
||||
def test_usage_list_paginated(self):
|
||||
usages = self.usages.list()
|
||||
|
||||
novaclient = self.stub_novaclient()
|
||||
novaclient.api_version = api_versions.APIVersion('2.40')
|
||||
novaclient.usage = self.mox.CreateMockAnything()
|
||||
novaclient.usage.list('start', 'end', True).AndReturn(usages)
|
||||
novaclient.usage.list(
|
||||
'start',
|
||||
'end',
|
||||
True,
|
||||
marker=u'063cf7f3-ded1-4297-bc4c-31eae876cc93',
|
||||
).AndReturn({})
|
||||
self.mox.ReplayAll()
|
||||
|
||||
ret_val = api.nova.usage_list(self.request, 'start', 'end')
|
||||
for usage in ret_val:
|
||||
self.assertIsInstance(usage, api.nova.NovaUsage)
|
||||
|
||||
def test_server_get(self):
|
||||
server = self.servers.first()
|
||||
|
||||
|
@ -139,7 +139,8 @@ USAGE_DATA = """
|
||||
"hours": 122.87361111111112,
|
||||
"vcpus": %(flavor_vcpus)s,
|
||||
"flavor": "%(flavor_name)s",
|
||||
"local_gb": %(flavor_disk)s
|
||||
"local_gb": %(flavor_disk)s,
|
||||
"instance_id": "063cf7f3-ded1-4297-bc4c-31eae876cc92"
|
||||
},
|
||||
{
|
||||
"memory_mb": %(flavor_ram)s,
|
||||
@ -152,7 +153,8 @@ USAGE_DATA = """
|
||||
"hours": 2.608611111111111,
|
||||
"vcpus": %(flavor_vcpus)s,
|
||||
"flavor": "%(flavor_name)s",
|
||||
"local_gb": %(flavor_disk)s
|
||||
"local_gb": %(flavor_disk)s,
|
||||
"instance_id": "063cf7f3-ded1-4297-bc4c-31eae876cc93"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user