Add support to expose default quotas for tenants

Neutron client should be able to show the default quotas
set for tenants. This patch adds support for the same and
introduces a new CLI to retrieve default quotas.

Sample usage:

neutron quota-default-show
+-----------------------+-------+
| Field                 | Value |
+-----------------------+-------+
| floatingip            | 50    |
| l2-gateway-connection | -1    |
| network               | 10    |
| port                  | 50    |
| rbac_policy           | 10    |
| router                | 10    |
| security_group        | 10    |
| security_group_rule   | 100   |
| subnet                | 10    |
| subnetpool            | -1    |
+-----------------------+-------+

Change-Id: Ie92c22862d2b8ace32a2cf4cb642a6d0bac7932d
Closes-Bug: #1204956
This commit is contained in:
Abhishek Raut 2016-05-03 05:17:12 -07:00
parent 20047f2ad0
commit d45442b3d4
5 changed files with 73 additions and 24 deletions

View File

@ -16,6 +16,7 @@
from __future__ import print_function
import abc
import argparse
from cliff import lister
@ -90,14 +91,17 @@ class ListQuota(neutronV20.NeutronCommand, lister.Lister):
for s in info))
class ShowQuota(neutronV20.NeutronCommand, show.ShowOne):
"""Show quotas of a given tenant.
class ShowQuotaBase(neutronV20.NeutronCommand, show.ShowOne):
"""Base class to show quotas of a given tenant."""
"""
resource = "quota"
@abc.abstractmethod
def retrieve_data(self, tenant_id, neutron_client):
"""Retrieve data using neutron client for the given tenant."""
def get_parser(self, prog_name):
parser = super(ShowQuota, self).get_parser(prog_name)
parser = super(ShowQuotaBase, self).get_parser(prog_name)
parser.add_argument(
'--tenant-id', metavar='tenant-id',
help=_('The owner tenant ID.'))
@ -115,27 +119,24 @@ class ShowQuota(neutronV20.NeutronCommand, show.ShowOne):
def take_action(self, parsed_args):
neutron_client = self.get_client()
tenant_id = get_tenant_id(parsed_args, neutron_client)
params = {}
obj_shower = getattr(neutron_client,
"show_%s" % self.resource)
data = obj_shower(tenant_id, **params)
data = self.retrieve_data(tenant_id, neutron_client)
if self.resource in data:
for k, v in six.iteritems(data[self.resource]):
if isinstance(v, list):
value = ""
for _item in v:
if value:
value += "\n"
if isinstance(_item, dict):
value += jsonutils.dumps(_item)
else:
value += str(_item)
data[self.resource][k] = value
elif v is None:
data[self.resource][k] = ''
return zip(*sorted(six.iteritems(data[self.resource])))
else:
return None
return
class ShowQuota(ShowQuotaBase):
"""Show quotas for a given tenant."""
def retrieve_data(self, tenant_id, neutron_client):
return neutron_client.show_quota(tenant_id)
class ShowQuotaDefault(ShowQuotaBase):
"""Show default quotas for a given tenant."""
def retrieve_data(self, tenant_id, neutron_client):
return neutron_client.show_quota_default(tenant_id)
class UpdateQuota(neutronV20.NeutronCommand, show.ShowOne):
@ -240,4 +241,4 @@ class UpdateQuota(neutronV20.NeutronCommand, show.ShowOne):
data[self.resource][k] = ''
return zip(*sorted(six.iteritems(data[self.resource])))
else:
return None
return

View File

@ -181,6 +181,7 @@ COMMAND_V2 = {
'purge': purge.Purge,
'quota-list': quota.ListQuota,
'quota-show': quota.ShowQuota,
'quota-default-show': quota.ShowQuotaDefault,
'quota-delete': quota.DeleteQuota,
'quota-update': quota.UpdateQuota,
'ext-list': extension.ListExt,

View File

@ -16,6 +16,8 @@
import sys
from mox3 import mox
from neutronclient.common import exceptions
from neutronclient.neutron.v2_0 import quota as test_quota
from neutronclient.tests.unit import test_cli20
@ -59,3 +61,34 @@ class CLITestV20Quota(test_cli20.CLITestV20Base):
exceptions.NeutronClientException, self._test_update_resource,
resource, cmd, self.test_id, args=args,
extrafields={'network': 'new'})
def test_show_quota_default(self):
resource = 'quota'
cmd = test_quota.ShowQuotaDefault(
test_cli20.MyApp(sys.stdout), None)
args = ['--tenant-id', self.test_id]
self.mox.StubOutWithMock(cmd, "get_client")
self.mox.StubOutWithMock(self.client.httpclient, "request")
cmd.get_client().MultipleTimes().AndReturn(self.client)
expected_res = {'quota': {'port': 50, 'network': 10, 'subnet': 10}}
resstr = self.client.serialize(expected_res)
path = getattr(self.client, "quota_default_path")
return_tup = (test_cli20.MyResp(200), resstr)
self.client.httpclient.request(
test_cli20.end_url(path % self.test_id), 'GET',
body=None,
headers=mox.ContainsKeyValue(
'X-Auth-Token', test_cli20.TOKEN)).AndReturn(return_tup)
self.mox.ReplayAll()
cmd_parser = cmd.get_parser("test_" + resource)
parsed_args = cmd_parser.parse_args(args)
cmd.run(parsed_args)
self.mox.VerifyAll()
self.mox.UnsetStubs()
_str = self.fake_stdout.make_string()
self.assertIn('network', _str)
self.assertIn('subnet', _str)
self.assertIn('port', _str)
self.assertNotIn('subnetpool', _str)

View File

@ -411,6 +411,7 @@ class Client(ClientBase):
address_scope_path = "/address-scopes/%s"
quotas_path = "/quotas"
quota_path = "/quotas/%s"
quota_default_path = "/quotas/%s/default"
extensions_path = "/extensions"
extension_path = "/extensions/%s"
routers_path = "/routers"
@ -602,6 +603,12 @@ class Client(ClientBase):
"""Fetch information of a certain project's quotas."""
return self.get(self.quota_path % (project_id), params=_params)
@debtcollector.renames.renamed_kwarg(
'tenant_id', 'project_id', replace=True)
def show_quota_default(self, project_id, **_params):
"""Fetch information of a certain project's default quotas."""
return self.get(self.quota_default_path % (project_id), params=_params)
@debtcollector.renames.renamed_kwarg(
'tenant_id', 'project_id', replace=True)
def update_quota(self, project_id, body=None):

View File

@ -0,0 +1,7 @@
---
features:
- |
CLI support to display the default quota reserved for a tenant.
* The ``quota-default-show`` command outputs the default quota
of resources for a given tenant.