Skip to content

Commit 06afa9b

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Use the compute SDK in usage commands"
2 parents d09aef5 + ce4cbea commit 06afa9b

2 files changed

Lines changed: 48 additions & 66 deletions

File tree

openstackclient/compute/v2/usage.py

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515

1616
"""Usage action implementations"""
1717

18-
import collections
1918
import datetime
2019
import functools
2120

2221
from cliff import columns as cliff_columns
23-
from novaclient import api_versions
2422
from osc_lib.command import command
2523
from osc_lib import utils
2624

@@ -58,7 +56,7 @@ def human_readable(self):
5856
class CountColumn(cliff_columns.FormattableColumn):
5957

6058
def human_readable(self):
61-
return len(self._value)
59+
return len(self._value) if self._value is not None else None
6260

6361

6462
class FloatColumn(cliff_columns.FormattableColumn):
@@ -69,7 +67,7 @@ def human_readable(self):
6967

7068
def _formatters(project_cache):
7169
return {
72-
'tenant_id': functools.partial(
70+
'project_id': functools.partial(
7371
ProjectColumn, project_cache=project_cache),
7472
'server_usages': CountColumn,
7573
'total_memory_mb_usage': FloatColumn,
@@ -102,10 +100,10 @@ def _merge_usage(usage, next_usage):
102100

103101
def _merge_usage_list(usages, next_usage_list):
104102
for next_usage in next_usage_list:
105-
if next_usage.tenant_id in usages:
106-
_merge_usage(usages[next_usage.tenant_id], next_usage)
103+
if next_usage.project_id in usages:
104+
_merge_usage(usages[next_usage.project_id], next_usage)
107105
else:
108-
usages[next_usage.tenant_id] = next_usage
106+
usages[next_usage.project_id] = next_usage
109107

110108

111109
class ListUsage(command.Lister):
@@ -138,9 +136,9 @@ def _format_project(project):
138136
else:
139137
return project
140138

141-
compute_client = self.app.client_manager.compute
139+
compute_client = self.app.client_manager.sdk_connection.compute
142140
columns = (
143-
"tenant_id",
141+
"project_id",
144142
"server_usages",
145143
"total_memory_mb_usage",
146144
"total_vcpus_usage",
@@ -154,36 +152,25 @@ def _format_project(project):
154152
"Disk GB-Hours"
155153
)
156154

157-
dateformat = "%Y-%m-%d"
155+
date_cli_format = "%Y-%m-%d"
156+
date_api_format = "%Y-%m-%dT%H:%M:%S"
158157
now = datetime.datetime.utcnow()
159158

160159
if parsed_args.start:
161-
start = datetime.datetime.strptime(parsed_args.start, dateformat)
160+
start = datetime.datetime.strptime(
161+
parsed_args.start, date_cli_format)
162162
else:
163163
start = now - datetime.timedelta(weeks=4)
164164

165165
if parsed_args.end:
166-
end = datetime.datetime.strptime(parsed_args.end, dateformat)
166+
end = datetime.datetime.strptime(parsed_args.end, date_cli_format)
167167
else:
168168
end = now + datetime.timedelta(days=1)
169169

170-
if compute_client.api_version < api_versions.APIVersion("2.40"):
171-
usage_list = compute_client.usage.list(start, end, detailed=True)
172-
else:
173-
# If the number of instances used to calculate the usage is greater
174-
# than CONF.api.max_limit, the usage will be split across multiple
175-
# requests and the responses will need to be merged back together.
176-
usages = collections.OrderedDict()
177-
usage_list = compute_client.usage.list(start, end, detailed=True)
178-
_merge_usage_list(usages, usage_list)
179-
marker = _get_usage_list_marker(usage_list)
180-
while marker:
181-
next_usage_list = compute_client.usage.list(
182-
start, end, detailed=True, marker=marker)
183-
marker = _get_usage_list_marker(next_usage_list)
184-
if marker:
185-
_merge_usage_list(usages, next_usage_list)
186-
usage_list = list(usages.values())
170+
usage_list = list(compute_client.usages(
171+
start=start.strftime(date_api_format),
172+
end=end.strftime(date_api_format),
173+
detailed=True))
187174

188175
# Cache the project list
189176
project_cache = {}
@@ -196,8 +183,8 @@ def _format_project(project):
196183

197184
if parsed_args.formatter == 'table' and len(usage_list) > 0:
198185
self.app.stdout.write(_("Usage from %(start)s to %(end)s: \n") % {
199-
"start": start.strftime(dateformat),
200-
"end": end.strftime(dateformat),
186+
"start": start.strftime(date_cli_format),
187+
"end": end.strftime(date_cli_format),
201188
})
202189

203190
return (
@@ -239,17 +226,19 @@ def get_parser(self, prog_name):
239226

240227
def take_action(self, parsed_args):
241228
identity_client = self.app.client_manager.identity
242-
compute_client = self.app.client_manager.compute
243-
dateformat = "%Y-%m-%d"
229+
compute_client = self.app.client_manager.sdk_connection.compute
230+
date_cli_format = "%Y-%m-%d"
231+
date_api_format = "%Y-%m-%dT%H:%M:%S"
244232
now = datetime.datetime.utcnow()
245233

246234
if parsed_args.start:
247-
start = datetime.datetime.strptime(parsed_args.start, dateformat)
235+
start = datetime.datetime.strptime(
236+
parsed_args.start, date_cli_format)
248237
else:
249238
start = now - datetime.timedelta(weeks=4)
250239

251240
if parsed_args.end:
252-
end = datetime.datetime.strptime(parsed_args.end, dateformat)
241+
end = datetime.datetime.strptime(parsed_args.end, date_cli_format)
253242
else:
254243
end = now + datetime.timedelta(days=1)
255244

@@ -262,19 +251,21 @@ def take_action(self, parsed_args):
262251
# Get the project from the current auth
263252
project = self.app.client_manager.auth_ref.project_id
264253

265-
usage = compute_client.usage.get(project, start, end)
254+
usage = compute_client.get_usage(
255+
project=project, start=start.strftime(date_api_format),
256+
end=end.strftime(date_api_format))
266257

267258
if parsed_args.formatter == 'table':
268259
self.app.stdout.write(_(
269260
"Usage from %(start)s to %(end)s on project %(project)s: \n"
270261
) % {
271-
"start": start.strftime(dateformat),
272-
"end": end.strftime(dateformat),
262+
"start": start.strftime(date_cli_format),
263+
"end": end.strftime(date_cli_format),
273264
"project": project,
274265
})
275266

276267
columns = (
277-
"tenant_id",
268+
"project_id",
278269
"server_usages",
279270
"total_memory_mb_usage",
280271
"total_vcpus_usage",

openstackclient/tests/unit/compute/v2/test_usage.py

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@
1111
# under the License.
1212
#
1313

14-
import datetime
1514
from unittest import mock
1615

17-
from novaclient import api_versions
18-
1916
from openstackclient.compute.v2 import usage as usage_cmds
2017
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
2118
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
@@ -26,8 +23,9 @@ class TestUsage(compute_fakes.TestComputev2):
2623
def setUp(self):
2724
super(TestUsage, self).setUp()
2825

29-
self.usage_mock = self.app.client_manager.compute.usage
30-
self.usage_mock.reset_mock()
26+
self.app.client_manager.sdk_connection = mock.Mock()
27+
self.app.client_manager.sdk_connection.compute = mock.Mock()
28+
self.sdk_client = self.app.client_manager.sdk_connection.compute
3129

3230
self.projects_mock = self.app.client_manager.identity.projects
3331
self.projects_mock.reset_mock()
@@ -38,7 +36,7 @@ class TestUsageList(TestUsage):
3836
project = identity_fakes.FakeProject.create_one_project()
3937
# Return value of self.usage_mock.list().
4038
usages = compute_fakes.FakeUsage.create_usages(
41-
attrs={'tenant_id': project.name}, count=1)
39+
attrs={'project_id': project.name}, count=1)
4240

4341
columns = (
4442
"Project",
@@ -49,7 +47,7 @@ class TestUsageList(TestUsage):
4947
)
5048

5149
data = [(
52-
usage_cmds.ProjectColumn(usages[0].tenant_id),
50+
usage_cmds.ProjectColumn(usages[0].project_id),
5351
usage_cmds.CountColumn(usages[0].server_usages),
5452
usage_cmds.FloatColumn(usages[0].total_memory_mb_usage),
5553
usage_cmds.FloatColumn(usages[0].total_vcpus_usage),
@@ -59,7 +57,7 @@ class TestUsageList(TestUsage):
5957
def setUp(self):
6058
super(TestUsageList, self).setUp()
6159

62-
self.usage_mock.list.return_value = self.usages
60+
self.sdk_client.usages.return_value = self.usages
6361

6462
self.projects_mock.list.return_value = [self.project]
6563
# Get the command object to test
@@ -97,9 +95,9 @@ def test_usage_list_with_options(self):
9795
columns, data = self.cmd.take_action(parsed_args)
9896

9997
self.projects_mock.list.assert_called_with()
100-
self.usage_mock.list.assert_called_with(
101-
datetime.datetime(2016, 11, 11, 0, 0),
102-
datetime.datetime(2016, 12, 20, 0, 0),
98+
self.sdk_client.usages.assert_called_with(
99+
start='2016-11-11T00:00:00',
100+
end='2016-12-20T00:00:00',
103101
detailed=True)
104102

105103
self.assertCountEqual(self.columns, columns)
@@ -112,20 +110,13 @@ def test_usage_list_with_pagination(self):
112110
('end', None),
113111
]
114112

115-
self.app.client_manager.compute.api_version = api_versions.APIVersion(
116-
'2.40')
117-
self.usage_mock.list.reset_mock()
118-
self.usage_mock.list.side_effect = [self.usages, []]
119-
120113
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
121114

122115
columns, data = self.cmd.take_action(parsed_args)
123116

124117
self.projects_mock.list.assert_called_with()
125-
self.usage_mock.list.assert_has_calls([
126-
mock.call(mock.ANY, mock.ANY, detailed=True),
127-
mock.call(mock.ANY, mock.ANY, detailed=True,
128-
marker=self.usages[0]['server_usages'][0]['instance_id'])
118+
self.sdk_client.usages.assert_has_calls([
119+
mock.call(start=mock.ANY, end=mock.ANY, detailed=True)
129120
])
130121
self.assertCountEqual(self.columns, columns)
131122
self.assertCountEqual(tuple(self.data), tuple(data))
@@ -136,7 +127,7 @@ class TestUsageShow(TestUsage):
136127
project = identity_fakes.FakeProject.create_one_project()
137128
# Return value of self.usage_mock.list().
138129
usage = compute_fakes.FakeUsage.create_one_usage(
139-
attrs={'tenant_id': project.name})
130+
attrs={'project_id': project.name})
140131

141132
columns = (
142133
'Project',
@@ -147,7 +138,7 @@ class TestUsageShow(TestUsage):
147138
)
148139

149140
data = (
150-
usage_cmds.ProjectColumn(usage.tenant_id),
141+
usage_cmds.ProjectColumn(usage.project_id),
151142
usage_cmds.CountColumn(usage.server_usages),
152143
usage_cmds.FloatColumn(usage.total_memory_mb_usage),
153144
usage_cmds.FloatColumn(usage.total_vcpus_usage),
@@ -157,7 +148,7 @@ class TestUsageShow(TestUsage):
157148
def setUp(self):
158149
super(TestUsageShow, self).setUp()
159150

160-
self.usage_mock.get.return_value = self.usage
151+
self.sdk_client.get_usage.return_value = self.usage
161152

162153
self.projects_mock.get.return_value = self.project
163154
# Get the command object to test
@@ -199,10 +190,10 @@ def test_usage_show_with_options(self):
199190

200191
columns, data = self.cmd.take_action(parsed_args)
201192

202-
self.usage_mock.get.assert_called_with(
203-
self.project.id,
204-
datetime.datetime(2016, 11, 11, 0, 0),
205-
datetime.datetime(2016, 12, 20, 0, 0))
193+
self.sdk_client.get_usage.assert_called_with(
194+
project=self.project.id,
195+
start='2016-11-11T00:00:00',
196+
end='2016-12-20T00:00:00')
206197

207198
self.assertEqual(self.columns, columns)
208199
self.assertEqual(self.data, data)

0 commit comments

Comments
 (0)