@@ -97,12 +97,164 @@ def _xform_get_quota(data, value, keys):
9797 return res
9898
9999
100- class ListQuota (command .Lister ):
101- _description = _ ("List quotas for all projects "
102- "with non-default quota values" )
100+ class BaseQuota (object ):
101+ def _get_project (self , parsed_args ):
102+ if parsed_args .project is not None :
103+ identity_client = self .app .client_manager .identity
104+ project = utils .find_resource (
105+ identity_client .projects ,
106+ parsed_args .project ,
107+ )
108+ project_id = project .id
109+ project_name = project .name
110+ elif self .app .client_manager .auth_ref :
111+ # Get the project from the current auth
112+ project = self .app .client_manager .auth_ref
113+ project_id = project .project_id
114+ project_name = project .project_name
115+ else :
116+ project = None
117+ project_id = None
118+ project_name = None
119+ project_info = {}
120+ project_info ['id' ] = project_id
121+ project_info ['name' ] = project_name
122+ return project_info
123+
124+ def get_compute_quota (self , client , parsed_args ):
125+ quota_class = (
126+ parsed_args .quota_class if 'quota_class' in parsed_args else False )
127+ detail = parsed_args .detail if 'detail' in parsed_args else False
128+ default = parsed_args .default if 'default' in parsed_args else False
129+ try :
130+ if quota_class :
131+ quota = client .quota_classes .get (parsed_args .project )
132+ else :
133+ project_info = self ._get_project (parsed_args )
134+ project = project_info ['id' ]
135+ if default :
136+ quota = client .quotas .defaults (project )
137+ else :
138+ quota = client .quotas .get (project , detail = detail )
139+ except Exception as e :
140+ if type (e ).__name__ == 'EndpointNotFound' :
141+ return {}
142+ else :
143+ raise
144+ return quota ._info
145+
146+ def get_volume_quota (self , client , parsed_args ):
147+ quota_class = (
148+ parsed_args .quota_class if 'quota_class' in parsed_args else False )
149+ default = parsed_args .default if 'default' in parsed_args else False
150+ try :
151+ if quota_class :
152+ quota = client .quota_classes .get (parsed_args .project )
153+ else :
154+ project_info = self ._get_project (parsed_args )
155+ project = project_info ['id' ]
156+ if default :
157+ quota = client .quotas .defaults (project )
158+ else :
159+ quota = client .quotas .get (project )
160+ except Exception as e :
161+ if type (e ).__name__ == 'EndpointNotFound' :
162+ return {}
163+ else :
164+ raise
165+ return quota ._info
166+
167+ def get_network_quota (self , parsed_args ):
168+ quota_class = (
169+ parsed_args .quota_class if 'quota_class' in parsed_args else False )
170+ detail = parsed_args .detail if 'detail' in parsed_args else False
171+ default = parsed_args .default if 'default' in parsed_args else False
172+ if quota_class :
173+ return {}
174+ if self .app .client_manager .is_network_endpoint_enabled ():
175+ project_info = self ._get_project (parsed_args )
176+ project = project_info ['id' ]
177+ client = self .app .client_manager .network
178+ if default :
179+ network_quota = client .get_quota_default (project )
180+ if type (network_quota ) is not dict :
181+ network_quota = network_quota .to_dict ()
182+ else :
183+ network_quota = client .get_quota (project ,
184+ details = detail )
185+ if type (network_quota ) is not dict :
186+ network_quota = network_quota .to_dict ()
187+ if detail :
188+ # NOTE(slaweq): Neutron returns values with key "used" but
189+ # Nova for example returns same data with key "in_use"
190+ # instead.
191+ # Because of that we need to convert Neutron key to
192+ # the same as is returned from Nova to make result
193+ # more consistent
194+ for key , values in network_quota .items ():
195+ if type (values ) is dict and "used" in values :
196+ values [u'in_use' ] = values .pop ("used" )
197+ network_quota [key ] = values
198+ return network_quota
199+ else :
200+ return {}
201+
202+
203+ class ListQuota (command .Lister , BaseQuota ):
204+ _description = _ (
205+ "List quotas for all projects with non-default quota values or "
206+ "list detailed quota informations for requested project" )
207+
208+ def _get_detailed_quotas (self , parsed_args ):
209+ columns = (
210+ 'resource' ,
211+ 'in_use' ,
212+ 'reserved' ,
213+ 'limit'
214+ )
215+ column_headers = (
216+ 'Resource' ,
217+ 'In Use' ,
218+ 'Reserved' ,
219+ 'Limit'
220+ )
221+ quotas = {}
222+ if parsed_args .compute :
223+ quotas .update (self .get_compute_quota (
224+ self .app .client_manager .compute , parsed_args ))
225+ if parsed_args .network :
226+ quotas .update (self .get_network_quota (parsed_args ))
227+
228+ result = []
229+ for resource , values in quotas .items ():
230+ # NOTE(slaweq): there is no detailed quotas info for some resources
231+ # and it should't be displayed here
232+ if type (values ) is dict :
233+ result .append ({
234+ 'resource' : resource ,
235+ 'in_use' : values .get ('in_use' ),
236+ 'reserved' : values .get ('reserved' ),
237+ 'limit' : values .get ('limit' )
238+ })
239+ return (column_headers ,
240+ (utils .get_dict_properties (
241+ s , columns ,
242+ ) for s in result ))
103243
104244 def get_parser (self , prog_name ):
105245 parser = super (ListQuota , self ).get_parser (prog_name )
246+ parser .add_argument (
247+ '--project' ,
248+ metavar = '<project>' ,
249+ help = _ ('List quotas for this project <project> (name or ID)' ),
250+ )
251+ parser .add_argument (
252+ '--detail' ,
253+ dest = 'detail' ,
254+ action = 'store_true' ,
255+ default = False ,
256+ help = _ ('Show details about quotas usage' )
257+ )
106258 option = parser .add_mutually_exclusive_group (required = True )
107259 option .add_argument (
108260 '--compute' ,
@@ -130,6 +282,8 @@ def take_action(self, parsed_args):
130282 project_ids = [getattr (p , 'id' , '' ) for p in projects ]
131283
132284 if parsed_args .compute :
285+ if parsed_args .detail :
286+ return self ._get_detailed_quotas (parsed_args )
133287 compute_client = self .app .client_manager .compute
134288 for p in project_ids :
135289 try :
@@ -193,6 +347,9 @@ def take_action(self, parsed_args):
193347 ) for s in result ))
194348
195349 if parsed_args .volume :
350+ if parsed_args .detail :
351+ LOG .warning ("Volume service doesn't provide detailed quota"
352+ " information" )
196353 volume_client = self .app .client_manager .volume
197354 for p in project_ids :
198355 try :
@@ -243,6 +400,8 @@ def take_action(self, parsed_args):
243400 ) for s in result ))
244401
245402 if parsed_args .network :
403+ if parsed_args .detail :
404+ return self ._get_detailed_quotas (parsed_args )
246405 client = self .app .client_manager .network
247406 for p in project_ids :
248407 try :
@@ -410,7 +569,7 @@ def take_action(self, parsed_args):
410569 ** network_kwargs )
411570
412571
413- class ShowQuota (command .ShowOne ):
572+ class ShowQuota (command .ShowOne , BaseQuota ):
414573 _description = _ ("Show quotas for project or class" )
415574
416575 def get_parser (self , prog_name ):
@@ -438,62 +597,6 @@ def get_parser(self, prog_name):
438597 )
439598 return parser
440599
441- def _get_project (self , parsed_args ):
442- if parsed_args .project is not None :
443- identity_client = self .app .client_manager .identity
444- project = utils .find_resource (
445- identity_client .projects ,
446- parsed_args .project ,
447- )
448- project_id = project .id
449- project_name = project .name
450- elif self .app .client_manager .auth_ref :
451- # Get the project from the current auth
452- project = self .app .client_manager .auth_ref
453- project_id = project .project_id
454- project_name = project .project_name
455- else :
456- project = None
457- project_id = None
458- project_name = None
459- project_info = {}
460- project_info ['id' ] = project_id
461- project_info ['name' ] = project_name
462- return project_info
463-
464- def get_compute_volume_quota (self , client , parsed_args ):
465- try :
466- if parsed_args .quota_class :
467- quota = client .quota_classes .get (parsed_args .project )
468- else :
469- project_info = self ._get_project (parsed_args )
470- project = project_info ['id' ]
471- if parsed_args .default :
472- quota = client .quotas .defaults (project )
473- else :
474- quota = client .quotas .get (project )
475- except Exception as e :
476- if type (e ).__name__ == 'EndpointNotFound' :
477- return {}
478- else :
479- raise
480- return quota ._info
481-
482- def get_network_quota (self , parsed_args ):
483- if parsed_args .quota_class :
484- return {}
485- if self .app .client_manager .is_network_endpoint_enabled ():
486- project_info = self ._get_project (parsed_args )
487- project = project_info ['id' ]
488- client = self .app .client_manager .network
489- if parsed_args .default :
490- network_quota = client .get_quota_default (project )
491- else :
492- network_quota = client .get_quota (project )
493- return network_quota
494- else :
495- return {}
496-
497600 def take_action (self , parsed_args ):
498601
499602 compute_client = self .app .client_manager .compute
@@ -504,10 +607,10 @@ def take_action(self, parsed_args):
504607 # does not exist. If this is determined to be the
505608 # intended behaviour of the API we will validate
506609 # the argument with Identity ourselves later.
507- compute_quota_info = self .get_compute_volume_quota (compute_client ,
508- parsed_args )
509- volume_quota_info = self .get_compute_volume_quota (volume_client ,
510- parsed_args )
610+ compute_quota_info = self .get_compute_quota (compute_client ,
611+ parsed_args )
612+ volume_quota_info = self .get_volume_quota (volume_client ,
613+ parsed_args )
511614 network_quota_info = self .get_network_quota (parsed_args )
512615 # NOTE(reedip): Remove the below check once requirement for
513616 # Openstack SDK is fixed to version 0.9.12 and above
0 commit comments