Skip to content

Commit 58591d3

Browse files
committed
OSC Quota List
Implement Neutron feature of Quota List into OpenStack Client. Change-Id: Idf941acf8d00b136776b7381b877c56d82622f57 Partially-Implements: blueprint neutron-client-quota
1 parent 35c308e commit 58591d3

9 files changed

Lines changed: 547 additions & 0 deletions

File tree

doc/source/command-objects/quota.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ single object with multiple properties.
77

88
Block Storage v1, v2, Compute v2, Network v2
99

10+
quota list
11+
----------
12+
13+
List quotas for all projects with non-default quota values
14+
15+
.. program:: quota list
16+
.. code:: bash
17+
18+
openstack quota list
19+
--compute | --network | --volume
20+
21+
.. option:: --network
22+
23+
List network quotas
24+
25+
.. option:: --compute
26+
27+
List compute quotas
28+
29+
.. option:: --volume
30+
31+
List volume quotas
32+
1033
quota set
1134
---------
1235

openstackclient/common/quota.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"""Quota action implementations"""
1717

1818
import itertools
19+
import logging
1920
import sys
2021

2122
from osc_lib.command import command
@@ -25,6 +26,8 @@
2526
from openstackclient.i18n import _
2627

2728

29+
LOG = logging.getLogger(__name__)
30+
2831
# List the quota items, map the internal argument name to the option
2932
# name that the user sees.
3033

@@ -78,6 +81,176 @@
7881
'l7policy': 'l7policies',
7982
}
8083

84+
NETWORK_KEYS = ['floating_ips', 'networks', 'rbac_policies', 'routers',
85+
'ports', 'security_group_rules', 'security_groups',
86+
'subnet_pools', 'subnets']
87+
88+
89+
def _xform_get_quota(data, value, keys):
90+
res = []
91+
res_info = {}
92+
for key in keys:
93+
res_info[key] = getattr(data, key, '')
94+
95+
res_info['id'] = value
96+
res.append(res_info)
97+
return res
98+
99+
100+
class ListQuota(command.Lister):
101+
_description = _("List quotas for all projects "
102+
"with non-default quota values")
103+
104+
def get_parser(self, prog_name):
105+
parser = super(ListQuota, self).get_parser(prog_name)
106+
option = parser.add_mutually_exclusive_group(required=True)
107+
option.add_argument(
108+
'--compute',
109+
action='store_true',
110+
default=False,
111+
help=_('List compute quota'),
112+
)
113+
option.add_argument(
114+
'--volume',
115+
action='store_true',
116+
default=False,
117+
help=_('List volume quota'),
118+
)
119+
option.add_argument(
120+
'--network',
121+
action='store_true',
122+
default=False,
123+
help=_('List network quota'),
124+
)
125+
return parser
126+
127+
def take_action(self, parsed_args):
128+
projects = self.app.client_manager.identity.projects.list()
129+
result = []
130+
project_ids = [getattr(p, 'id', '') for p in projects]
131+
132+
if parsed_args.compute:
133+
compute_client = self.app.client_manager.compute
134+
for p in project_ids:
135+
data = compute_client.quotas.get(p)
136+
result_data = _xform_get_quota(data, p,
137+
COMPUTE_QUOTAS.keys())
138+
default_data = compute_client.quotas.defaults(p)
139+
result_default = _xform_get_quota(default_data,
140+
p,
141+
COMPUTE_QUOTAS.keys())
142+
if result_default != result_data:
143+
result += result_data
144+
145+
columns = (
146+
'id',
147+
'cores',
148+
'fixed_ips',
149+
'injected_files',
150+
'injected_file_content_bytes',
151+
'injected_file_path_bytes',
152+
'instances',
153+
'key_pairs',
154+
'metadata_items',
155+
'ram',
156+
'server_groups',
157+
'server_group_members',
158+
)
159+
column_headers = (
160+
'Project ID',
161+
'Cores',
162+
'Fixed IPs',
163+
'Injected Files',
164+
'Injected File Content Bytes',
165+
'Injected File Path Bytes',
166+
'Instances',
167+
'Key Pairs',
168+
'Metadata Items',
169+
'Ram',
170+
'Server Groups',
171+
'Server Group Members',
172+
)
173+
return (column_headers,
174+
(utils.get_dict_properties(
175+
s, columns,
176+
) for s in result))
177+
if parsed_args.volume:
178+
volume_client = self.app.client_manager.volume
179+
for p in project_ids:
180+
data = volume_client.quotas.get(p)
181+
result_data = _xform_get_quota(data, p,
182+
VOLUME_QUOTAS.keys())
183+
default_data = volume_client.quotas.defaults(p)
184+
result_default = _xform_get_quota(default_data,
185+
p,
186+
VOLUME_QUOTAS.keys())
187+
if result_default != result_data:
188+
result += result_data
189+
190+
columns = (
191+
'id',
192+
'backups',
193+
'backup_gigabytes',
194+
'gigabytes',
195+
'per_volume_gigabytes',
196+
'snapshots',
197+
'volumes',
198+
)
199+
column_headers = (
200+
'Project ID',
201+
'Backups',
202+
'Backup Gigabytes',
203+
'Gigabytes',
204+
'Per Volume Gigabytes',
205+
'Snapshots',
206+
'Volumes',
207+
)
208+
return (column_headers,
209+
(utils.get_dict_properties(
210+
s, columns,
211+
) for s in result))
212+
if parsed_args.network:
213+
client = self.app.client_manager.network
214+
for p in project_ids:
215+
data = client.get_quota(p)
216+
result_data = _xform_get_quota(data, p, NETWORK_KEYS)
217+
default_data = client.get_quota_default(p)
218+
result_default = _xform_get_quota(default_data,
219+
p, NETWORK_KEYS)
220+
if result_default != result_data:
221+
result += result_data
222+
223+
columns = (
224+
'id',
225+
'floating_ips',
226+
'networks',
227+
'ports',
228+
'rbac_policies',
229+
'routers',
230+
'security_groups',
231+
'security_group_rules',
232+
'subnets',
233+
'subnet_pools',
234+
)
235+
column_headers = (
236+
'Project ID',
237+
'Floating IPs',
238+
'Networks',
239+
'Ports',
240+
'RBAC Policies',
241+
'Routers',
242+
'Security Groups',
243+
'Security Group Rules',
244+
'Subnets',
245+
'Subnet Pools'
246+
)
247+
return (column_headers,
248+
(utils.get_dict_properties(
249+
s, columns,
250+
) for s in result))
251+
252+
return ((), ())
253+
81254

82255
class SetQuota(command.Command):
83256
_description = _("Set quotas for project or class")

openstackclient/tests/functional/common/test_quota.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,27 @@ def setUpClass(cls):
2525
cls.PROJECT_NAME =\
2626
cls.get_openstack_configuration_value('auth.project_name')
2727

28+
def test_quota_list_network_option(self):
29+
self.openstack('quota set --networks 40 ' +
30+
self.PROJECT_NAME)
31+
raw_output = self.openstack('quota list --network')
32+
self.assertIsNotNone(raw_output)
33+
self.assertIn("40", raw_output)
34+
35+
def test_quota_list_compute_option(self):
36+
self.openstack('quota set --instances 40 ' +
37+
self.PROJECT_NAME)
38+
raw_output = self.openstack('quota list --compute')
39+
self.assertIsNotNone(raw_output)
40+
self.assertIn("40", raw_output)
41+
42+
def test_quota_list_volume_option(self):
43+
self.openstack('quota set --backups 40 ' +
44+
self.PROJECT_NAME)
45+
raw_output = self.openstack('quota list --volume')
46+
self.assertIsNotNone(raw_output)
47+
self.assertIn("40", raw_output)
48+
2849
def test_quota_set(self):
2950
self.openstack('quota set --instances 11 --volumes 11 --networks 11 ' +
3051
self.PROJECT_NAME)

0 commit comments

Comments
 (0)