Merge "Simple tenant usage pagination"
This commit is contained in:
commit
fe8e7714c3
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import collections
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.conf import settings
|
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 _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from novaclient import api_versions
|
||||||
from novaclient import client as nova_client
|
from novaclient import client as nova_client
|
||||||
from novaclient import exceptions as nova_exceptions
|
from novaclient import exceptions as nova_exceptions
|
||||||
from novaclient.v2.contrib import instance_action as nova_instance_action
|
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)
|
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
|
@profiler.trace
|
||||||
def usage_get(request, tenant_id, start, end):
|
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
|
@profiler.trace
|
||||||
def usage_list(request, start, end):
|
def usage_list(request, start, end):
|
||||||
return [NovaUsage(u) for u in
|
client = novaclient(request)
|
||||||
novaclient(request).usage.list(start, end, True)]
|
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
|
@profiler.trace
|
||||||
|
@ -24,6 +24,7 @@ from django import http
|
|||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
from mox3.mox import IsA # noqa
|
from mox3.mox import IsA # noqa
|
||||||
|
from novaclient import api_versions
|
||||||
from novaclient import exceptions as nova_exceptions
|
from novaclient import exceptions as nova_exceptions
|
||||||
from novaclient.v2 import flavor_access as nova_flavor_access
|
from novaclient.v2 import flavor_access as nova_flavor_access
|
||||||
from novaclient.v2 import servers
|
from novaclient.v2 import servers
|
||||||
@ -201,6 +202,24 @@ class ComputeApiTests(test.APITestCase):
|
|||||||
'start', 'end')
|
'start', 'end')
|
||||||
self.assertIsInstance(ret_val, api.nova.NovaUsage)
|
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):
|
def test_usage_list(self):
|
||||||
usages = self.usages.list()
|
usages = self.usages.list()
|
||||||
|
|
||||||
@ -213,6 +232,25 @@ class ComputeApiTests(test.APITestCase):
|
|||||||
for usage in ret_val:
|
for usage in ret_val:
|
||||||
self.assertIsInstance(usage, api.nova.NovaUsage)
|
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):
|
def test_server_get(self):
|
||||||
server = self.servers.first()
|
server = self.servers.first()
|
||||||
|
|
||||||
|
@ -139,7 +139,8 @@ USAGE_DATA = """
|
|||||||
"hours": 122.87361111111112,
|
"hours": 122.87361111111112,
|
||||||
"vcpus": %(flavor_vcpus)s,
|
"vcpus": %(flavor_vcpus)s,
|
||||||
"flavor": "%(flavor_name)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,
|
"memory_mb": %(flavor_ram)s,
|
||||||
@ -152,7 +153,8 @@ USAGE_DATA = """
|
|||||||
"hours": 2.608611111111111,
|
"hours": 2.608611111111111,
|
||||||
"vcpus": %(flavor_vcpus)s,
|
"vcpus": %(flavor_vcpus)s,
|
||||||
"flavor": "%(flavor_name)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