Revert "Microversion 2.39 - Simple tenant usage pagination"
This reverts commit f47393dbbf
.
The 2.39 microversion has not been merged in Nova, and this
change is missing a functional test to show the support added
here, which if present would have required a depends-on to the
Nova change for the 2.39 support. So this needs to come back
out until it's ready.
Change-Id: I6b6990b9a4e1e7cfea1d2aabe5f2464614440360
This commit is contained in:
parent
f47393dbbf
commit
5c4d436d21
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
|||||||
# when client supported the max version, and bumped sequentially, otherwise
|
# when client supported the max version, and bumped sequentially, otherwise
|
||||||
# the client may break due to server side new version may include some
|
# the client may break due to server side new version may include some
|
||||||
# backward incompatible change.
|
# backward incompatible change.
|
||||||
API_MAX_VERSION = api_versions.APIVersion("2.39")
|
API_MAX_VERSION = api_versions.APIVersion("2.38")
|
||||||
|
@ -73,7 +73,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
self.auth_url = 'auth_url'
|
self.auth_url = 'auth_url'
|
||||||
self.tenant_id = 'tenant_id'
|
self.tenant_id = 'tenant_id'
|
||||||
self.callstack = []
|
self.callstack = []
|
||||||
self.visited = []
|
|
||||||
self.projectid = 'projectid'
|
self.projectid = 'projectid'
|
||||||
self.user = 'user'
|
self.user = 'user'
|
||||||
self.region_name = 'region_name'
|
self.region_name = 'region_name'
|
||||||
@ -136,21 +135,12 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
v2_image = True
|
v2_image = True
|
||||||
callback = callback.replace('get_v2_', 'get_')
|
callback = callback.replace('get_v2_', 'get_')
|
||||||
|
|
||||||
simulate_pagination_next_links = [
|
|
||||||
'get_os_simple_tenant_usage',
|
|
||||||
'get_os_simple_tenant_usage_tenant_id',
|
|
||||||
]
|
|
||||||
if callback in simulate_pagination_next_links:
|
|
||||||
while callback in self.visited:
|
|
||||||
callback += '_next'
|
|
||||||
|
|
||||||
if not hasattr(self, callback):
|
if not hasattr(self, callback):
|
||||||
raise AssertionError('Called unknown API method: %s %s, '
|
raise AssertionError('Called unknown API method: %s %s, '
|
||||||
'expected fakes method name: %s' %
|
'expected fakes method name: %s' %
|
||||||
(method, url, callback))
|
(method, url, callback))
|
||||||
|
|
||||||
# Note the call
|
# Note the call
|
||||||
self.visited.append(callback)
|
|
||||||
self.callstack.append((method, url, kwargs.get('body')))
|
self.callstack.append((method, url, kwargs.get('body')))
|
||||||
|
|
||||||
status, headers, body = getattr(self, callback)(**kwargs)
|
status, headers, body = getattr(self, callback)(**kwargs)
|
||||||
@ -1575,8 +1565,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
six.u('name'): six.u('f15image1'),
|
six.u('name'): six.u('f15image1'),
|
||||||
six.u('tenant_id'):
|
six.u('tenant_id'):
|
||||||
six.u('7b0a1d73f8fb41718f3343c207597869'),
|
six.u('7b0a1d73f8fb41718f3343c207597869'),
|
||||||
six.u('instance_id'):
|
|
||||||
six.u('f079e394-1111-457b-b350-bb5ecc685cdd'),
|
|
||||||
six.u('vcpus'): 1,
|
six.u('vcpus'): 1,
|
||||||
six.u('memory_mb'): 512,
|
six.u('memory_mb'): 512,
|
||||||
six.u('state'): six.u('active'),
|
six.u('state'): six.u('active'),
|
||||||
@ -1586,37 +1574,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
six.u('start'): six.u('2011-12-25 19:48:41.750687'),
|
six.u('start'): six.u('2011-12-25 19:48:41.750687'),
|
||||||
six.u('total_local_gb_usage'): 0.0}]})
|
six.u('total_local_gb_usage'): 0.0}]})
|
||||||
|
|
||||||
def get_os_simple_tenant_usage_next(self, **kw):
|
|
||||||
return (200, FAKE_RESPONSE_HEADERS,
|
|
||||||
{six.u('tenant_usages'): [{
|
|
||||||
six.u('total_memory_mb_usage'): 25451.762807466665,
|
|
||||||
six.u('total_vcpus_usage'): 49.71047423333333,
|
|
||||||
six.u('total_hours'): 49.71047423333333,
|
|
||||||
six.u('tenant_id'):
|
|
||||||
six.u('7b0a1d73f8fb41718f3343c207597869'),
|
|
||||||
six.u('stop'): six.u('2012-01-22 19:48:41.750722'),
|
|
||||||
six.u('server_usages'): [{
|
|
||||||
six.u('hours'): 49.71047423333333,
|
|
||||||
six.u('uptime'): 27035,
|
|
||||||
six.u('local_gb'): 0,
|
|
||||||
six.u('ended_at'): None,
|
|
||||||
six.u('name'): six.u('f15image1'),
|
|
||||||
six.u('tenant_id'):
|
|
||||||
six.u('7b0a1d73f8fb41718f3343c207597869'),
|
|
||||||
six.u('instance_id'):
|
|
||||||
six.u('f079e394-2222-457b-b350-bb5ecc685cdd'),
|
|
||||||
six.u('vcpus'): 1,
|
|
||||||
six.u('memory_mb'): 512,
|
|
||||||
six.u('state'): six.u('active'),
|
|
||||||
six.u('flavor'): six.u('m1.tiny'),
|
|
||||||
six.u('started_at'):
|
|
||||||
six.u('2012-01-20 18:06:06.479998')}],
|
|
||||||
six.u('start'): six.u('2011-12-25 19:48:41.750687'),
|
|
||||||
six.u('total_local_gb_usage'): 0.0}]})
|
|
||||||
|
|
||||||
def get_os_simple_tenant_usage_next_next(self, **kw):
|
|
||||||
return (200, FAKE_RESPONSE_HEADERS, {six.u('tenant_usages'): []})
|
|
||||||
|
|
||||||
def get_os_simple_tenant_usage_tenantfoo(self, **kw):
|
def get_os_simple_tenant_usage_tenantfoo(self, **kw):
|
||||||
return (200, FAKE_RESPONSE_HEADERS,
|
return (200, FAKE_RESPONSE_HEADERS,
|
||||||
{six.u('tenant_usage'): {
|
{six.u('tenant_usage'): {
|
||||||
@ -1633,8 +1590,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
six.u('name'): six.u('f15image1'),
|
six.u('name'): six.u('f15image1'),
|
||||||
six.u('tenant_id'):
|
six.u('tenant_id'):
|
||||||
six.u('7b0a1d73f8fb41718f3343c207597869'),
|
six.u('7b0a1d73f8fb41718f3343c207597869'),
|
||||||
six.u('instance_id'):
|
|
||||||
six.u('f079e394-1111-457b-b350-bb5ecc685cdd'),
|
|
||||||
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
||||||
six.u('state'): six.u('active'),
|
six.u('state'): six.u('active'),
|
||||||
six.u('flavor'): six.u('m1.tiny'),
|
six.u('flavor'): six.u('m1.tiny'),
|
||||||
@ -1656,8 +1611,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
six.u('ended_at'): None,
|
six.u('ended_at'): None,
|
||||||
six.u('name'): six.u('f15image1'),
|
six.u('name'): six.u('f15image1'),
|
||||||
six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
|
six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
|
||||||
six.u('instance_id'):
|
|
||||||
six.u('f079e394-1111-457b-b350-bb5ecc685cdd'),
|
|
||||||
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
||||||
six.u('state'): six.u('active'),
|
six.u('state'): six.u('active'),
|
||||||
six.u('flavor'): six.u('m1.tiny'),
|
six.u('flavor'): six.u('m1.tiny'),
|
||||||
@ -1678,8 +1631,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
six.u('ended_at'): None,
|
six.u('ended_at'): None,
|
||||||
six.u('name'): six.u('f15image1'),
|
six.u('name'): six.u('f15image1'),
|
||||||
six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
|
six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
|
||||||
six.u('instance_id'):
|
|
||||||
six.u('f079e394-1111-457b-b350-bb5ecc685cdd'),
|
|
||||||
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
||||||
six.u('state'): six.u('active'),
|
six.u('state'): six.u('active'),
|
||||||
six.u('flavor'): six.u('m1.tiny'),
|
six.u('flavor'): six.u('m1.tiny'),
|
||||||
@ -1687,31 +1638,6 @@ class FakeHTTPClient(base_client.HTTPClient):
|
|||||||
six.u('start'): six.u('2011-12-25 19:48:41.750687'),
|
six.u('start'): six.u('2011-12-25 19:48:41.750687'),
|
||||||
six.u('total_local_gb_usage'): 0.0}})
|
six.u('total_local_gb_usage'): 0.0}})
|
||||||
|
|
||||||
def get_os_simple_tenant_usage_tenant_id_next(self, **kw):
|
|
||||||
return (200, {}, {six.u('tenant_usage'): {
|
|
||||||
six.u('total_memory_mb_usage'): 25451.762807466665,
|
|
||||||
six.u('total_vcpus_usage'): 49.71047423333333,
|
|
||||||
six.u('total_hours'): 49.71047423333333,
|
|
||||||
six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
|
|
||||||
six.u('stop'): six.u('2012-01-22 19:48:41.750722'),
|
|
||||||
six.u('server_usages'): [{
|
|
||||||
six.u('hours'): 49.71047423333333,
|
|
||||||
six.u('uptime'): 27035, six.u('local_gb'): 0,
|
|
||||||
six.u('ended_at'): None,
|
|
||||||
six.u('name'): six.u('f15image1'),
|
|
||||||
six.u('tenant_id'): six.u('7b0a1d73f8fb41718f3343c207597869'),
|
|
||||||
six.u('instance_id'):
|
|
||||||
six.u('f079e394-2222-457b-b350-bb5ecc685cdd'),
|
|
||||||
six.u('vcpus'): 1, six.u('memory_mb'): 512,
|
|
||||||
six.u('state'): six.u('active'),
|
|
||||||
six.u('flavor'): six.u('m1.tiny'),
|
|
||||||
six.u('started_at'): six.u('2012-01-20 18:06:06.479998')}],
|
|
||||||
six.u('start'): six.u('2011-12-25 19:48:41.750687'),
|
|
||||||
six.u('total_local_gb_usage'): 0.0}})
|
|
||||||
|
|
||||||
def get_os_simple_tenant_usage_tenant_id_next_next(self, **kw):
|
|
||||||
return (200, {}, {six.u('tenant_usage'): {}})
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Aggregates
|
# Aggregates
|
||||||
#
|
#
|
||||||
@ -2451,7 +2377,6 @@ class FakeSessionMockClient(base_client.SessionClient, FakeHTTPClient):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
self.callstack = []
|
self.callstack = []
|
||||||
self.visited = []
|
|
||||||
self.auth = mock.Mock()
|
self.auth = mock.Mock()
|
||||||
self.session = mock.Mock()
|
self.session = mock.Mock()
|
||||||
self.session.get_endpoint.return_value = FakeHTTPClient.get_endpoint(
|
self.session.get_endpoint.return_value = FakeHTTPClient.get_endpoint(
|
||||||
|
@ -50,7 +50,7 @@ class ShellFixture(fixtures.Fixture):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# For some method like test_image_meta_bad_action we are
|
# For some method like test_image_meta_bad_action we are
|
||||||
# testing a SystemExit to be thrown and object self.shell has
|
# testing a SystemExit to be thrown and object self.shell has
|
||||||
# no time to get instantiated which is OK in this case, so
|
# no time to get instantatiated which is OK in this case, so
|
||||||
# we make sure the method is there before launching it.
|
# we make sure the method is there before launching it.
|
||||||
if hasattr(self.shell, 'cs'):
|
if hasattr(self.shell, 'cs'):
|
||||||
self.shell.cs.clear_callstack()
|
self.shell.cs.clear_callstack()
|
||||||
@ -1750,36 +1750,12 @@ class ShellTest(utils.TestCase):
|
|||||||
{'removeFloatingIp': {'address': '11.0.0.1'}})
|
{'removeFloatingIp': {'address': '11.0.0.1'}})
|
||||||
|
|
||||||
def test_usage_list(self):
|
def test_usage_list(self):
|
||||||
cmd = 'usage-list --start 2000-01-20 --end 2005-02-01'
|
self.run_command('usage-list --start 2000-01-20 --end 2005-02-01')
|
||||||
stdout, _ = self.run_command(cmd)
|
|
||||||
self.assert_called('GET',
|
self.assert_called('GET',
|
||||||
'/os-simple-tenant-usage?' +
|
'/os-simple-tenant-usage?' +
|
||||||
'start=2000-01-20T00:00:00&' +
|
'start=2000-01-20T00:00:00&' +
|
||||||
'end=2005-02-01T00:00:00&' +
|
'end=2005-02-01T00:00:00&' +
|
||||||
'detailed=1')
|
'detailed=1')
|
||||||
# Servers, RAM MB-Hours, CPU Hours, Disk GB-Hours
|
|
||||||
self.assertIn('1 | 25451.76 | 49.71 | 0.00', stdout)
|
|
||||||
|
|
||||||
def test_usage_list_stitch_together_next_results(self):
|
|
||||||
cmd = 'usage-list --start 2000-01-20 --end 2005-02-01'
|
|
||||||
stdout, _ = self.run_command(cmd, api_version='2.39')
|
|
||||||
self.assert_called('GET',
|
|
||||||
'/os-simple-tenant-usage?'
|
|
||||||
'start=2000-01-20T00:00:00&'
|
|
||||||
'end=2005-02-01T00:00:00&'
|
|
||||||
'detailed=1', pos=0)
|
|
||||||
markers = [
|
|
||||||
'f079e394-1111-457b-b350-bb5ecc685cdd',
|
|
||||||
'f079e394-2222-457b-b350-bb5ecc685cdd',
|
|
||||||
]
|
|
||||||
for pos, marker in enumerate(markers):
|
|
||||||
self.assert_called('GET',
|
|
||||||
'/os-simple-tenant-usage?'
|
|
||||||
'start=2000-01-20T00:00:00&'
|
|
||||||
'end=2005-02-01T00:00:00&'
|
|
||||||
'marker=%s&detailed=1' % (marker), pos=pos + 1)
|
|
||||||
# Servers, RAM MB-Hours, CPU Hours, Disk GB-Hours
|
|
||||||
self.assertIn('2 | 50903.53 | 99.42 | 0.00', stdout)
|
|
||||||
|
|
||||||
def test_usage_list_no_args(self):
|
def test_usage_list_no_args(self):
|
||||||
timeutils.set_time_override(datetime.datetime(2005, 2, 1, 0, 0))
|
timeutils.set_time_override(datetime.datetime(2005, 2, 1, 0, 0))
|
||||||
@ -1792,34 +1768,12 @@ class ShellTest(utils.TestCase):
|
|||||||
'detailed=1')
|
'detailed=1')
|
||||||
|
|
||||||
def test_usage(self):
|
def test_usage(self):
|
||||||
cmd = 'usage --start 2000-01-20 --end 2005-02-01 --tenant test'
|
self.run_command('usage --start 2000-01-20 --end 2005-02-01 '
|
||||||
stdout, _ = self.run_command(cmd)
|
'--tenant test')
|
||||||
self.assert_called('GET',
|
self.assert_called('GET',
|
||||||
'/os-simple-tenant-usage/test?' +
|
'/os-simple-tenant-usage/test?' +
|
||||||
'start=2000-01-20T00:00:00&' +
|
'start=2000-01-20T00:00:00&' +
|
||||||
'end=2005-02-01T00:00:00')
|
'end=2005-02-01T00:00:00')
|
||||||
# Servers, RAM MB-Hours, CPU Hours, Disk GB-Hours
|
|
||||||
self.assertIn('1 | 25451.76 | 49.71 | 0.00', stdout)
|
|
||||||
|
|
||||||
def test_usage_stitch_together_next_results(self):
|
|
||||||
cmd = 'usage --start 2000-01-20 --end 2005-02-01'
|
|
||||||
stdout, _ = self.run_command(cmd, api_version='2.39')
|
|
||||||
self.assert_called('GET',
|
|
||||||
'/os-simple-tenant-usage/tenant_id?'
|
|
||||||
'start=2000-01-20T00:00:00&'
|
|
||||||
'end=2005-02-01T00:00:00', pos=0)
|
|
||||||
markers = [
|
|
||||||
'f079e394-1111-457b-b350-bb5ecc685cdd',
|
|
||||||
'f079e394-2222-457b-b350-bb5ecc685cdd',
|
|
||||||
]
|
|
||||||
for pos, marker in enumerate(markers):
|
|
||||||
self.assert_called('GET',
|
|
||||||
'/os-simple-tenant-usage/tenant_id?'
|
|
||||||
'start=2000-01-20T00:00:00&'
|
|
||||||
'end=2005-02-01T00:00:00&'
|
|
||||||
'marker=%s' % (marker), pos=pos + 1)
|
|
||||||
# Servers, RAM MB-Hours, CPU Hours, Disk GB-Hours
|
|
||||||
self.assertIn('2 | 50903.53 | 99.42 | 0.00', stdout)
|
|
||||||
|
|
||||||
def test_usage_no_tenant(self):
|
def test_usage_no_tenant(self):
|
||||||
self.run_command('usage --start 2000-01-20 --end 2005-02-01')
|
self.run_command('usage --start 2000-01-20 --end 2005-02-01')
|
||||||
|
@ -73,52 +73,3 @@ class UsageTest(utils.TestCase):
|
|||||||
'GET',
|
'GET',
|
||||||
"/os-simple-tenant-usage/tenantfoo?start=%s&end=%s" %
|
"/os-simple-tenant-usage/tenantfoo?start=%s&end=%s" %
|
||||||
(start, stop))
|
(start, stop))
|
||||||
|
|
||||||
|
|
||||||
class UsageV39Test(UsageTest):
|
|
||||||
def setUp(self):
|
|
||||||
super(UsageV39Test, self).setUp()
|
|
||||||
self.cs.api_version = api_versions.APIVersion('2.39')
|
|
||||||
|
|
||||||
def test_usage_list_with_paging(self):
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
usages = self.cs.usage.list(now, now, marker='some-uuid', limit=3)
|
|
||||||
self.assert_request_id(usages, fakes.FAKE_REQUEST_ID_LIST)
|
|
||||||
|
|
||||||
self.cs.assert_called(
|
|
||||||
'GET',
|
|
||||||
'/os-simple-tenant-usage?' +
|
|
||||||
('start=%s&' % now.isoformat()) +
|
|
||||||
('end=%s&' % now.isoformat()) +
|
|
||||||
('limit=3&marker=some-uuid&detailed=0'))
|
|
||||||
for u in usages:
|
|
||||||
self.assertIsInstance(u, usage.Usage)
|
|
||||||
|
|
||||||
def test_usage_list_detailed_with_paging(self):
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
usages = self.cs.usage.list(
|
|
||||||
now, now, detailed=True, marker='some-uuid', limit=3)
|
|
||||||
self.assert_request_id(usages, fakes.FAKE_REQUEST_ID_LIST)
|
|
||||||
|
|
||||||
self.cs.assert_called(
|
|
||||||
'GET',
|
|
||||||
'/os-simple-tenant-usage?' +
|
|
||||||
('start=%s&' % now.isoformat()) +
|
|
||||||
('end=%s&' % now.isoformat()) +
|
|
||||||
('limit=3&marker=some-uuid&detailed=1'))
|
|
||||||
for u in usages:
|
|
||||||
self.assertIsInstance(u, usage.Usage)
|
|
||||||
|
|
||||||
def test_usage_get_with_paging(self):
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
u = self.cs.usage.get(
|
|
||||||
'tenantfoo', now, now, marker='some-uuid', limit=3)
|
|
||||||
self.assert_request_id(u, fakes.FAKE_REQUEST_ID_LIST)
|
|
||||||
|
|
||||||
self.cs.assert_called(
|
|
||||||
'GET',
|
|
||||||
'/os-simple-tenant-usage/tenantfoo?' +
|
|
||||||
('start=%s&' % now.isoformat()) +
|
|
||||||
('end=%s&' % now.isoformat()) +
|
|
||||||
('limit=3&marker=some-uuid'))
|
|
||||||
self.assertIsInstance(u, usage.Usage)
|
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import collections
|
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
@ -3434,43 +3433,7 @@ def do_usage_list(cs, args):
|
|||||||
setattr(u, simplerows[3], "%.2f" % u.total_vcpus_usage)
|
setattr(u, simplerows[3], "%.2f" % u.total_vcpus_usage)
|
||||||
setattr(u, simplerows[4], "%.2f" % u.total_local_gb_usage)
|
setattr(u, simplerows[4], "%.2f" % u.total_local_gb_usage)
|
||||||
|
|
||||||
def get_marker(usage_list):
|
|
||||||
marker = None
|
|
||||||
if usage_list:
|
|
||||||
usage = usage_list[-1]
|
|
||||||
if hasattr(usage, 'server_usages') and usage.server_usages:
|
|
||||||
marker = usage.server_usages[-1]['instance_id']
|
|
||||||
return marker
|
|
||||||
|
|
||||||
def merge_usage(usages, next_usage_list):
|
|
||||||
for next_usage in next_usage_list:
|
|
||||||
if next_usage.tenant_id in usages:
|
|
||||||
usage = usages[next_usage.tenant_id]
|
|
||||||
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
|
|
||||||
else:
|
|
||||||
usages[next_usage.tenant_id] = next_usage
|
|
||||||
|
|
||||||
if cs.api_version < api_versions.APIVersion('2.39'):
|
|
||||||
usage_list = cs.usage.list(start, end, detailed=True)
|
usage_list = cs.usage.list(start, end, detailed=True)
|
||||||
else:
|
|
||||||
# If the number of instances used to calculate the usage is greater
|
|
||||||
# than osapi_max_limit, the usage will be split across multiple
|
|
||||||
# requests and the responses will need to be merged back together.
|
|
||||||
usages = collections.OrderedDict()
|
|
||||||
usage_list = cs.usage.list(start, end, detailed=True)
|
|
||||||
merge_usage(usages, usage_list)
|
|
||||||
marker = get_marker(usage_list)
|
|
||||||
while marker:
|
|
||||||
next_usage_list = cs.usage.list(
|
|
||||||
start, end, detailed=True, marker=marker)
|
|
||||||
marker = get_marker(next_usage_list)
|
|
||||||
if marker:
|
|
||||||
merge_usage(usages, next_usage_list)
|
|
||||||
usage_list = usages.values()
|
|
||||||
|
|
||||||
print(_("Usage from %(start)s to %(end)s:") %
|
print(_("Usage from %(start)s to %(end)s:") %
|
||||||
{'start': start.strftime(dateformat),
|
{'start': start.strftime(dateformat),
|
||||||
@ -3521,41 +3484,15 @@ def do_usage(cs, args):
|
|||||||
setattr(u, simplerows[2], "%.2f" % u.total_vcpus_usage)
|
setattr(u, simplerows[2], "%.2f" % u.total_vcpus_usage)
|
||||||
setattr(u, simplerows[3], "%.2f" % u.total_local_gb_usage)
|
setattr(u, simplerows[3], "%.2f" % u.total_local_gb_usage)
|
||||||
|
|
||||||
def get_marker(usage):
|
|
||||||
marker = None
|
|
||||||
if hasattr(usage, 'server_usages') and usage.server_usages:
|
|
||||||
marker = usage.server_usages[-1]['instance_id']
|
|
||||||
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
|
|
||||||
|
|
||||||
if args.tenant:
|
if args.tenant:
|
||||||
tenant_id = args.tenant
|
usage = cs.usage.get(args.tenant, start, end)
|
||||||
else:
|
else:
|
||||||
if isinstance(cs.client, client.SessionClient):
|
if isinstance(cs.client, client.SessionClient):
|
||||||
auth = cs.client.auth
|
auth = cs.client.auth
|
||||||
tenant_id = auth.get_auth_ref(cs.client.session).project_id
|
project_id = auth.get_auth_ref(cs.client.session).project_id
|
||||||
|
usage = cs.usage.get(project_id, start, end)
|
||||||
else:
|
else:
|
||||||
tenant_id = cs.client.tenant_id
|
usage = cs.usage.get(cs.client.tenant_id, start, end)
|
||||||
|
|
||||||
if cs.api_version < api_versions.APIVersion('2.39'):
|
|
||||||
usage = cs.usage.get(tenant_id, start, end)
|
|
||||||
else:
|
|
||||||
# If the number of instances used to calculate the usage is greater
|
|
||||||
# than osapi_max_limit, the usage will be split across multiple
|
|
||||||
# requests and the responses will need to be merged back together.
|
|
||||||
usage = cs.usage.get(tenant_id, start, end)
|
|
||||||
marker = get_marker(usage)
|
|
||||||
while marker:
|
|
||||||
next_usage = cs.usage.get(tenant_id, start, end, marker=marker)
|
|
||||||
marker = get_marker(next_usage)
|
|
||||||
if marker:
|
|
||||||
merge_usage(usage, next_usage)
|
|
||||||
|
|
||||||
print(_("Usage from %(start)s to %(end)s:") %
|
print(_("Usage from %(start)s to %(end)s:") %
|
||||||
{'start': start.strftime(dateformat),
|
{'start': start.strftime(dateformat),
|
||||||
|
@ -17,7 +17,6 @@ Usage interface.
|
|||||||
|
|
||||||
import oslo_utils
|
import oslo_utils
|
||||||
|
|
||||||
from novaclient import api_versions
|
|
||||||
from novaclient import base
|
from novaclient import base
|
||||||
|
|
||||||
|
|
||||||
@ -47,19 +46,7 @@ class UsageManager(base.ManagerWithFind):
|
|||||||
Manage :class:`Usage` resources.
|
Manage :class:`Usage` resources.
|
||||||
"""
|
"""
|
||||||
resource_class = Usage
|
resource_class = Usage
|
||||||
usage_prefix = 'os-simple-tenant-usage'
|
|
||||||
|
|
||||||
def _usage_query(self, start, end, marker=None, limit=None, detailed=None):
|
|
||||||
query = "?start=%s&end=%s" % (start.isoformat(), end.isoformat())
|
|
||||||
if limit:
|
|
||||||
query = "%s&limit=%s" % (query, int(limit))
|
|
||||||
if marker:
|
|
||||||
query = "%s&marker=%s" % (query, marker)
|
|
||||||
if detailed is not None:
|
|
||||||
query = "%s&detailed=%s" % (query, int(bool(detailed)))
|
|
||||||
return query
|
|
||||||
|
|
||||||
@api_versions.wraps("2.0", "2.38")
|
|
||||||
def list(self, start, end, detailed=False):
|
def list(self, start, end, detailed=False):
|
||||||
"""
|
"""
|
||||||
Get usage for all tenants
|
Get usage for all tenants
|
||||||
@ -70,31 +57,11 @@ class UsageManager(base.ManagerWithFind):
|
|||||||
instance whose usage is part of the report
|
instance whose usage is part of the report
|
||||||
:rtype: list of :class:`Usage`.
|
:rtype: list of :class:`Usage`.
|
||||||
"""
|
"""
|
||||||
query_string = self._usage_query(start, end, detailed=detailed)
|
return self._list(
|
||||||
url = '/%s%s' % (self.usage_prefix, query_string)
|
"/os-simple-tenant-usage?start=%s&end=%s&detailed=%s" %
|
||||||
return self._list(url, 'tenant_usages')
|
(start.isoformat(), end.isoformat(), int(bool(detailed))),
|
||||||
|
"tenant_usages")
|
||||||
|
|
||||||
@api_versions.wraps("2.39")
|
|
||||||
def list(self, start, end, detailed=False, marker=None, limit=None):
|
|
||||||
"""
|
|
||||||
Get usage for all tenants
|
|
||||||
|
|
||||||
:param start: :class:`datetime.datetime` Start date in UTC
|
|
||||||
:param end: :class:`datetime.datetime` End date in UTC
|
|
||||||
:param detailed: Whether to include information about each
|
|
||||||
instance whose usage is part of the report
|
|
||||||
:param marker: Begin returning usage data for instances that appear
|
|
||||||
later in the instance list than that represented by
|
|
||||||
this instance UUID (optional).
|
|
||||||
:param limit: Maximum number of instances to include in the usage
|
|
||||||
(optional).
|
|
||||||
:rtype: list of :class:`Usage`.
|
|
||||||
"""
|
|
||||||
query_string = self._usage_query(start, end, marker, limit, detailed)
|
|
||||||
url = '/%s%s' % (self.usage_prefix, query_string)
|
|
||||||
return self._list(url, 'tenant_usages')
|
|
||||||
|
|
||||||
@api_versions.wraps("2.0", "2.38")
|
|
||||||
def get(self, tenant_id, start, end):
|
def get(self, tenant_id, start, end):
|
||||||
"""
|
"""
|
||||||
Get usage for a specific tenant.
|
Get usage for a specific tenant.
|
||||||
@ -104,25 +71,6 @@ class UsageManager(base.ManagerWithFind):
|
|||||||
:param end: :class:`datetime.datetime` End date in UTC
|
:param end: :class:`datetime.datetime` End date in UTC
|
||||||
:rtype: :class:`Usage`
|
:rtype: :class:`Usage`
|
||||||
"""
|
"""
|
||||||
query_string = self._usage_query(start, end)
|
return self._get("/os-simple-tenant-usage/%s?start=%s&end=%s" %
|
||||||
url = '/%s/%s%s' % (self.usage_prefix, tenant_id, query_string)
|
(tenant_id, start.isoformat(), end.isoformat()),
|
||||||
return self._get(url, 'tenant_usage')
|
"tenant_usage")
|
||||||
|
|
||||||
@api_versions.wraps("2.39")
|
|
||||||
def get(self, tenant_id, start, end, marker=None, limit=None):
|
|
||||||
"""
|
|
||||||
Get usage for a specific tenant.
|
|
||||||
|
|
||||||
:param tenant_id: Tenant ID to fetch usage for
|
|
||||||
:param start: :class:`datetime.datetime` Start date in UTC
|
|
||||||
:param end: :class:`datetime.datetime` End date in UTC
|
|
||||||
:param marker: Begin returning usage data for instances that appear
|
|
||||||
later in the instance list than that represented by
|
|
||||||
this instance UUID (optional).
|
|
||||||
:param limit: Maximum number of instances to include in the usage
|
|
||||||
(optional).
|
|
||||||
:rtype: :class:`Usage`
|
|
||||||
"""
|
|
||||||
query_string = self._usage_query(start, end, marker, limit)
|
|
||||||
url = '/%s/%s%s' % (self.usage_prefix, tenant_id, query_string)
|
|
||||||
return self._get(url, 'tenant_usage')
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
features:
|
|
||||||
- Added microversion v2.39 which introduces pagination support for usage
|
|
||||||
with the help of new optional parameters 'limit' and 'marker'.
|
|
Loading…
Reference in New Issue
Block a user