Skip to content

Commit 06263bd

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Fix limits show command without Nova and Cinder"
2 parents b59de7b + 24b06ef commit 06263bd

6 files changed

Lines changed: 383 additions & 11 deletions

File tree

openstackclient/common/clientmanager.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,25 @@ def is_network_endpoint_enabled(self):
125125
# use Network API by default
126126
return self.is_service_available('network') is not False
127127

128+
def is_compute_endpoint_enabled(self):
129+
"""Check if Compute endpoint is enabled"""
130+
131+
return self.is_service_available('compute') is not False
132+
133+
def is_volume_endpoint_enabled(self, volume_client):
134+
"""Check if volume endpoint is enabled"""
135+
# NOTE(jcross): Cinder did some interesting things with their service
136+
# name so we need to figure out which version to look
137+
# for when calling is_service_available()
138+
volume_version = volume_client.api_version.ver_major
139+
if self.is_service_available(
140+
"volumev%s" % volume_version) is not False:
141+
return True
142+
elif self.is_service_available('volume') is not False:
143+
return True
144+
else:
145+
return False
146+
128147

129148
# Plugin Support
130149

openstackclient/common/limits.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,24 +83,34 @@ def take_action(self, parsed_args):
8383
project_id = utils.find_resource(identity_client.projects,
8484
parsed_args.project).id
8585

86-
compute_limits = compute_client.limits.get(parsed_args.is_reserved,
87-
tenant_id=project_id)
88-
volume_limits = volume_client.limits.get()
86+
compute_limits = None
87+
volume_limits = None
8988

89+
if self.app.client_manager.is_compute_endpoint_enabled():
90+
compute_limits = compute_client.limits.get(parsed_args.is_reserved,
91+
tenant_id=project_id)
92+
93+
if self.app.client_manager.is_volume_endpoint_enabled(volume_client):
94+
volume_limits = volume_client.limits.get()
95+
96+
data = []
9097
if parsed_args.is_absolute:
91-
compute_limits = compute_limits.absolute
92-
volume_limits = volume_limits.absolute
98+
if compute_limits:
99+
data.append(compute_limits.absolute)
100+
if volume_limits:
101+
data.append(volume_limits.absolute)
93102
columns = ["Name", "Value"]
94103
return (columns, (utils.get_item_properties(s, columns)
95-
for s in itertools.chain(compute_limits, volume_limits)))
104+
for s in itertools.chain(*data)))
96105

97106
elif parsed_args.is_rate:
98-
compute_limits = compute_limits.rate
99-
volume_limits = volume_limits.rate
107+
if compute_limits:
108+
data.append(compute_limits.rate)
109+
if volume_limits:
110+
data.append(volume_limits.rate)
100111
columns = ["Verb", "URI", "Value", "Remain", "Unit",
101112
"Next Available"]
102113
return (columns, (utils.get_item_properties(s, columns)
103-
for s in itertools.chain(compute_limits, volume_limits)))
104-
114+
for s in itertools.chain(*data)))
105115
else:
106-
return ({}, {})
116+
return {}, {}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
13+
14+
from openstackclient.common import limits
15+
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
16+
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
17+
18+
19+
class TestComputeLimits(compute_fakes.TestComputev2):
20+
21+
absolute_columns = [
22+
'Name',
23+
'Value',
24+
]
25+
26+
rate_columns = [
27+
"Verb",
28+
"URI",
29+
"Value",
30+
"Remain",
31+
"Unit",
32+
"Next Available"
33+
]
34+
35+
def setUp(self):
36+
super(TestComputeLimits, self).setUp()
37+
self.app.client_manager.volume_endpoint_enabled = False
38+
self.compute = self.app.client_manager.compute
39+
40+
self.fake_limits = compute_fakes.FakeLimits()
41+
self.compute.limits.get.return_value = self.fake_limits
42+
43+
def test_compute_show_absolute(self):
44+
arglist = ['--absolute']
45+
verifylist = [('is_absolute', True)]
46+
cmd = limits.ShowLimits(self.app, None)
47+
parsed_args = self.check_parser(cmd, arglist, verifylist)
48+
49+
columns, data = cmd.take_action(parsed_args)
50+
51+
ret_limits = list(data)
52+
compute_reference_limits = self.fake_limits.absolute_limits()
53+
54+
self.assertEqual(self.absolute_columns, columns)
55+
self.assertEqual(compute_reference_limits, ret_limits)
56+
self.assertEqual(19, len(ret_limits))
57+
58+
def test_compute_show_rate(self):
59+
arglist = ['--rate']
60+
verifylist = [('is_rate', True)]
61+
cmd = limits.ShowLimits(self.app, None)
62+
parsed_args = self.check_parser(cmd, arglist, verifylist)
63+
64+
columns, data = cmd.take_action(parsed_args)
65+
66+
ret_limits = list(data)
67+
compute_reference_limits = self.fake_limits.rate_limits()
68+
69+
self.assertEqual(self.rate_columns, columns)
70+
self.assertEqual(compute_reference_limits, ret_limits)
71+
self.assertEqual(3, len(ret_limits))
72+
73+
74+
class TestVolumeLimits(volume_fakes.TestVolume):
75+
absolute_columns = [
76+
'Name',
77+
'Value',
78+
]
79+
80+
rate_columns = [
81+
"Verb",
82+
"URI",
83+
"Value",
84+
"Remain",
85+
"Unit",
86+
"Next Available"
87+
]
88+
89+
def setUp(self):
90+
super(TestVolumeLimits, self).setUp()
91+
self.app.client_manager.compute_endpoint_enabled = False
92+
self.volume = self.app.client_manager.volume
93+
94+
self.fake_limits = volume_fakes.FakeLimits()
95+
self.volume.limits.get.return_value = self.fake_limits
96+
97+
def test_volume_show_absolute(self):
98+
arglist = ['--absolute']
99+
verifylist = [('is_absolute', True)]
100+
cmd = limits.ShowLimits(self.app, None)
101+
parsed_args = self.check_parser(cmd, arglist, verifylist)
102+
103+
columns, data = cmd.take_action(parsed_args)
104+
105+
ret_limits = list(data)
106+
compute_reference_limits = self.fake_limits.absolute_limits()
107+
108+
self.assertEqual(self.absolute_columns, columns)
109+
self.assertEqual(compute_reference_limits, ret_limits)
110+
self.assertEqual(10, len(ret_limits))
111+
112+
def test_volume_show_rate(self):
113+
arglist = ['--rate']
114+
verifylist = [('is_rate', True)]
115+
cmd = limits.ShowLimits(self.app, None)
116+
parsed_args = self.check_parser(cmd, arglist, verifylist)
117+
118+
columns, data = cmd.take_action(parsed_args)
119+
120+
ret_limits = list(data)
121+
compute_reference_limits = self.fake_limits.rate_limits()
122+
123+
self.assertEqual(self.rate_columns, columns)
124+
self.assertEqual(compute_reference_limits, ret_limits)
125+
self.assertEqual(3, len(ret_limits))

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

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ def __init__(self, **kwargs):
149149
self.images = mock.Mock()
150150
self.images.resource_class = fakes.FakeResource(None, {})
151151

152+
self.limits = mock.Mock()
153+
self.limits.resource_class = fakes.FakeResource(None, {})
154+
152155
self.servers = mock.Mock()
153156
self.servers.resource_class = fakes.FakeResource(None, {})
154157

@@ -1392,3 +1395,110 @@ def create_one_default_comp_quota(attrs=None):
13921395
quota.project_id = quota_attrs['id']
13931396

13941397
return quota
1398+
1399+
1400+
class FakeLimits(object):
1401+
"""Fake limits"""
1402+
1403+
def __init__(self, absolute_attrs=None, rate_attrs=None):
1404+
self.absolute_limits_attrs = {
1405+
'maxServerMeta': 128,
1406+
'maxTotalInstances': 10,
1407+
'maxPersonality': 5,
1408+
'totalServerGroupsUsed': 0,
1409+
'maxImageMeta': 128,
1410+
'maxPersonalitySize': 10240,
1411+
'maxTotalRAMSize': 51200,
1412+
'maxServerGroups': 10,
1413+
'maxSecurityGroupRules': 20,
1414+
'maxTotalKeypairs': 100,
1415+
'totalCoresUsed': 0,
1416+
'totalRAMUsed': 0,
1417+
'maxSecurityGroups': 10,
1418+
'totalFloatingIpsUsed': 0,
1419+
'totalInstancesUsed': 0,
1420+
'maxServerGroupMembers': 10,
1421+
'maxTotalFloatingIps': 10,
1422+
'totalSecurityGroupsUsed': 0,
1423+
'maxTotalCores': 20,
1424+
}
1425+
absolute_attrs = absolute_attrs or {}
1426+
self.absolute_limits_attrs.update(absolute_attrs)
1427+
1428+
self.rate_limits_attrs = [{
1429+
"uri": "*",
1430+
"limit": [
1431+
{
1432+
"value": 10,
1433+
"verb": "POST",
1434+
"remaining": 2,
1435+
"unit": "MINUTE",
1436+
"next-available": "2011-12-15T22:42:45Z"
1437+
},
1438+
{
1439+
"value": 10,
1440+
"verb": "PUT",
1441+
"remaining": 2,
1442+
"unit": "MINUTE",
1443+
"next-available": "2011-12-15T22:42:45Z"
1444+
},
1445+
{
1446+
"value": 100,
1447+
"verb": "DELETE",
1448+
"remaining": 100,
1449+
"unit": "MINUTE",
1450+
"next-available": "2011-12-15T22:42:45Z"
1451+
}
1452+
]
1453+
}]
1454+
1455+
@property
1456+
def absolute(self):
1457+
for (name, value) in self.absolute_limits_attrs.items():
1458+
yield FakeAbsoluteLimit(name, value)
1459+
1460+
def absolute_limits(self):
1461+
reference_data = []
1462+
for (name, value) in self.absolute_limits_attrs.items():
1463+
reference_data.append((name, value))
1464+
return reference_data
1465+
1466+
@property
1467+
def rate(self):
1468+
for group in self.rate_limits_attrs:
1469+
uri = group['uri']
1470+
for rate in group['limit']:
1471+
yield FakeRateLimit(rate['verb'], uri, rate['value'],
1472+
rate['remaining'], rate['unit'],
1473+
rate['next-available'])
1474+
1475+
def rate_limits(self):
1476+
reference_data = []
1477+
for group in self.rate_limits_attrs:
1478+
uri = group['uri']
1479+
for rate in group['limit']:
1480+
reference_data.append((rate['verb'], uri, rate['value'],
1481+
rate['remaining'], rate['unit'],
1482+
rate['next-available']))
1483+
return reference_data
1484+
1485+
1486+
class FakeAbsoluteLimit(object):
1487+
"""Data model that represents an absolute limit"""
1488+
1489+
def __init__(self, name, value):
1490+
self.name = name
1491+
self.value = value
1492+
1493+
1494+
class FakeRateLimit(object):
1495+
"""Data model that represents a flattened view of a single rate limit"""
1496+
1497+
def __init__(self, verb, uri, value, remain,
1498+
unit, next_available):
1499+
self.verb = verb
1500+
self.uri = uri
1501+
self.value = value
1502+
self.remain = remain
1503+
self.unit = unit
1504+
self.next_available = next_available

openstackclient/tests/unit/fakes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ def __init__(self):
140140
self.auth_ref = None
141141
self.auth_plugin_name = None
142142
self.network_endpoint_enabled = True
143+
self.compute_endpoint_enabled = True
144+
self.volume_endpoint_enabled = True
143145

144146
def get_configuration(self):
145147
return {
@@ -155,6 +157,12 @@ def get_configuration(self):
155157
def is_network_endpoint_enabled(self):
156158
return self.network_endpoint_enabled
157159

160+
def is_compute_endpoint_enabled(self):
161+
return self.compute_endpoint_enabled
162+
163+
def is_volume_endpoint_enabled(self, client):
164+
return self.volume_endpoint_enabled
165+
158166

159167
class FakeModule(object):
160168

0 commit comments

Comments
 (0)