Merge "quota: Simplify logic used to list, show quotas"
This commit is contained in:
commit
351b2b1074
openstackclient
@ -25,7 +25,6 @@ from osc_lib import utils
|
|||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
from openstackclient.network import common
|
from openstackclient.network import common
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
# List the quota items, map the internal argument name to the option
|
# List the quota items, map the internal argument name to the option
|
||||||
@ -78,9 +77,17 @@ NETWORK_QUOTAS = {
|
|||||||
'subnetpool': 'subnetpools',
|
'subnetpool': 'subnetpools',
|
||||||
}
|
}
|
||||||
|
|
||||||
NETWORK_KEYS = ['floating_ips', 'networks', 'rbac_policies', 'routers',
|
NETWORK_KEYS = [
|
||||||
'ports', 'security_group_rules', 'security_groups',
|
'floating_ips',
|
||||||
'subnet_pools', 'subnets']
|
'networks',
|
||||||
|
'rbac_policies',
|
||||||
|
'routers',
|
||||||
|
'ports',
|
||||||
|
'security_group_rules',
|
||||||
|
'security_groups',
|
||||||
|
'subnet_pools',
|
||||||
|
'subnets',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def _xform_get_quota(data, value, keys):
|
def _xform_get_quota(data, value, keys):
|
||||||
@ -94,181 +101,151 @@ def _xform_get_quota(data, value, keys):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class BaseQuota(object):
|
def get_project(app, project):
|
||||||
def _get_project(self, parsed_args):
|
if project is not None:
|
||||||
if parsed_args.project is not None:
|
identity_client = app.client_manager.identity
|
||||||
identity_client = self.app.client_manager.identity
|
project = utils.find_resource(
|
||||||
project = utils.find_resource(
|
identity_client.projects,
|
||||||
identity_client.projects,
|
project,
|
||||||
parsed_args.project,
|
)
|
||||||
)
|
project_id = project.id
|
||||||
project_id = project.id
|
project_name = project.name
|
||||||
project_name = project.name
|
elif app.client_manager.auth_ref:
|
||||||
elif self.app.client_manager.auth_ref:
|
# Get the project from the current auth
|
||||||
# Get the project from the current auth
|
project = app.client_manager.auth_ref
|
||||||
project = self.app.client_manager.auth_ref
|
project_id = project.project_id
|
||||||
project_id = project.project_id
|
project_name = project.project_name
|
||||||
project_name = project.project_name
|
else:
|
||||||
|
project_id = None
|
||||||
|
project_name = None
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': project_id,
|
||||||
|
'name': project_name,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_compute_quotas(
|
||||||
|
app,
|
||||||
|
project_id,
|
||||||
|
*,
|
||||||
|
quota_class=False,
|
||||||
|
detail=False,
|
||||||
|
default=False,
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
client = app.client_manager.compute
|
||||||
|
if quota_class:
|
||||||
|
# NOTE(stephenfin): The 'project' argument here could be anything
|
||||||
|
# as the nova API doesn't care what you pass in. We only pass the
|
||||||
|
# project in to avoid weirding people out :)
|
||||||
|
quota = client.quota_classes.get(project_id)
|
||||||
|
elif default:
|
||||||
|
quota = client.quotas.defaults(project_id)
|
||||||
else:
|
else:
|
||||||
project = None
|
quota = client.quotas.get(project_id, detail=detail)
|
||||||
project_id = None
|
except Exception as e:
|
||||||
project_name = None
|
if type(e).__name__ == 'EndpointNotFound':
|
||||||
project_info = {}
|
return {}
|
||||||
project_info['id'] = project_id
|
raise
|
||||||
project_info['name'] = project_name
|
return quota._info
|
||||||
return project_info
|
|
||||||
|
|
||||||
def get_compute_quota(self, client, parsed_args):
|
|
||||||
quota_class = (
|
|
||||||
parsed_args.quota_class if 'quota_class' in parsed_args else False)
|
|
||||||
detail = parsed_args.detail if 'detail' in parsed_args else False
|
|
||||||
default = parsed_args.default if 'default' in parsed_args else False
|
|
||||||
try:
|
|
||||||
if quota_class:
|
|
||||||
quota = client.quota_classes.get(parsed_args.project)
|
|
||||||
else:
|
|
||||||
project_info = self._get_project(parsed_args)
|
|
||||||
project = project_info['id']
|
|
||||||
if default:
|
|
||||||
quota = client.quotas.defaults(project)
|
|
||||||
else:
|
|
||||||
quota = client.quotas.get(project, detail=detail)
|
|
||||||
except Exception as e:
|
|
||||||
if type(e).__name__ == 'EndpointNotFound':
|
|
||||||
return {}
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
return quota._info
|
|
||||||
|
|
||||||
def get_volume_quota(self, client, parsed_args):
|
def get_volume_quotas(
|
||||||
quota_class = (
|
app,
|
||||||
parsed_args.quota_class if 'quota_class' in parsed_args else False)
|
project_id,
|
||||||
detail = parsed_args.detail if 'detail' in parsed_args else False
|
*,
|
||||||
default = parsed_args.default if 'default' in parsed_args else False
|
quota_class=False,
|
||||||
try:
|
detail=False,
|
||||||
if quota_class:
|
default=False,
|
||||||
quota = client.quota_classes.get(parsed_args.project)
|
):
|
||||||
else:
|
try:
|
||||||
project_info = self._get_project(parsed_args)
|
client = app.client_manager.volume
|
||||||
project = project_info['id']
|
if quota_class:
|
||||||
if default:
|
quota = client.quota_classes.get(project_id)
|
||||||
quota = client.quotas.defaults(project)
|
elif default:
|
||||||
else:
|
quota = client.quotas.defaults(project_id)
|
||||||
quota = client.quotas.get(project, usage=detail)
|
else:
|
||||||
except Exception as e:
|
quota = client.quotas.get(project_id, usage=detail)
|
||||||
if type(e).__name__ == 'EndpointNotFound':
|
except Exception as e:
|
||||||
return {}
|
if type(e).__name__ == 'EndpointNotFound':
|
||||||
else:
|
return {}
|
||||||
raise
|
else:
|
||||||
return quota._info
|
raise
|
||||||
|
return quota._info
|
||||||
|
|
||||||
def _network_quota_to_dict(self, network_quota):
|
|
||||||
|
def get_network_quotas(
|
||||||
|
app,
|
||||||
|
project_id,
|
||||||
|
*,
|
||||||
|
quota_class=False,
|
||||||
|
detail=False,
|
||||||
|
default=False,
|
||||||
|
):
|
||||||
|
def _network_quota_to_dict(network_quota, detail=False):
|
||||||
if type(network_quota) is not dict:
|
if type(network_quota) is not dict:
|
||||||
dict_quota = network_quota.to_dict()
|
dict_quota = network_quota.to_dict()
|
||||||
else:
|
else:
|
||||||
dict_quota = network_quota
|
dict_quota = network_quota
|
||||||
return {k: v for k, v in dict_quota.items() if v is not None}
|
|
||||||
|
|
||||||
def get_network_quota(self, parsed_args):
|
result = {}
|
||||||
quota_class = (
|
|
||||||
parsed_args.quota_class if 'quota_class' in parsed_args else False)
|
for key, values in dict_quota.items():
|
||||||
detail = parsed_args.detail if 'detail' in parsed_args else False
|
if values is None:
|
||||||
default = parsed_args.default if 'default' in parsed_args else False
|
continue
|
||||||
if quota_class:
|
|
||||||
return {}
|
# NOTE(slaweq): Neutron returns values with key "used" but Nova for
|
||||||
if self.app.client_manager.is_network_endpoint_enabled():
|
# example returns same data with key "in_use" instead. Because of
|
||||||
project_info = self._get_project(parsed_args)
|
# that we need to convert Neutron key to the same as is returned
|
||||||
project = project_info['id']
|
# from Nova to make result more consistent
|
||||||
client = self.app.client_manager.network
|
if isinstance(values, dict) and 'used' in values:
|
||||||
if default:
|
values['in_use'] = values.pop("used")
|
||||||
network_quota = client.get_quota_default(project)
|
|
||||||
network_quota = self._network_quota_to_dict(network_quota)
|
result[key] = values
|
||||||
else:
|
|
||||||
network_quota = client.get_quota(project,
|
return result
|
||||||
details=detail)
|
|
||||||
network_quota = self._network_quota_to_dict(network_quota)
|
# neutron doesn't have the concept of quota classes and if we're using
|
||||||
if detail:
|
# nova-network we already fetched this
|
||||||
# NOTE(slaweq): Neutron returns values with key "used" but
|
if quota_class:
|
||||||
# Nova for example returns same data with key "in_use"
|
return {}
|
||||||
# instead.
|
|
||||||
# Because of that we need to convert Neutron key to
|
# we have nothing to return if we are not using neutron
|
||||||
# the same as is returned from Nova to make result
|
if not app.client_manager.is_network_endpoint_enabled():
|
||||||
# more consistent
|
return {}
|
||||||
for key, values in network_quota.items():
|
|
||||||
if type(values) is dict and "used" in values:
|
client = app.client_manager.network
|
||||||
values['in_use'] = values.pop("used")
|
if default:
|
||||||
network_quota[key] = values
|
network_quota = client.get_quota_default(project_id)
|
||||||
return network_quota
|
network_quota = _network_quota_to_dict(network_quota)
|
||||||
else:
|
else:
|
||||||
return {}
|
network_quota = client.get_quota(project_id, details=detail)
|
||||||
|
network_quota = _network_quota_to_dict(network_quota, detail=detail)
|
||||||
|
return network_quota
|
||||||
|
|
||||||
|
|
||||||
class ListQuota(command.Lister, BaseQuota):
|
class ListQuota(command.Lister):
|
||||||
_description = _(
|
_description = _(
|
||||||
"List quotas for all projects with non-default quota values or "
|
"List quotas for all projects with non-default quota values or "
|
||||||
"list detailed quota information for requested project"
|
"list detailed quota information for requested project"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_detailed_quotas(self, parsed_args):
|
|
||||||
columns = (
|
|
||||||
'resource',
|
|
||||||
'in_use',
|
|
||||||
'reserved',
|
|
||||||
'limit'
|
|
||||||
)
|
|
||||||
column_headers = (
|
|
||||||
'Resource',
|
|
||||||
'In Use',
|
|
||||||
'Reserved',
|
|
||||||
'Limit'
|
|
||||||
)
|
|
||||||
quotas = {}
|
|
||||||
if parsed_args.compute:
|
|
||||||
quotas.update(
|
|
||||||
self.get_compute_quota(
|
|
||||||
self.app.client_manager.compute,
|
|
||||||
parsed_args,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if parsed_args.network:
|
|
||||||
quotas.update(self.get_network_quota(parsed_args))
|
|
||||||
if parsed_args.volume:
|
|
||||||
quotas.update(
|
|
||||||
self.get_volume_quota(
|
|
||||||
self.app.client_manager.volume,
|
|
||||||
parsed_args,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
result = []
|
|
||||||
for resource, values in quotas.items():
|
|
||||||
# NOTE(slaweq): there is no detailed quotas info for some resources
|
|
||||||
# and it shouldn't be displayed here
|
|
||||||
if type(values) is dict:
|
|
||||||
result.append({
|
|
||||||
'resource': resource,
|
|
||||||
'in_use': values.get('in_use'),
|
|
||||||
'reserved': values.get('reserved'),
|
|
||||||
'limit': values.get('limit')
|
|
||||||
})
|
|
||||||
return (column_headers,
|
|
||||||
(utils.get_dict_properties(
|
|
||||||
s, columns,
|
|
||||||
) for s in result))
|
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(ListQuota, self).get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--project',
|
'--project',
|
||||||
metavar='<project>',
|
metavar='<project>',
|
||||||
help=_('List quotas for this project <project> (name or ID)'),
|
help=_('List quotas for this project <project> (name or ID)'),
|
||||||
)
|
)
|
||||||
|
# TODO(stephenfin): This doesn't belong here. We should put it into the
|
||||||
|
# 'quota show' command and deprecate this.
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--detail',
|
'--detail',
|
||||||
dest='detail',
|
dest='detail',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=False,
|
default=False,
|
||||||
help=_('Show details about quotas usage')
|
help=_('Show details about quotas usage'),
|
||||||
)
|
)
|
||||||
option = parser.add_mutually_exclusive_group(required=True)
|
option = parser.add_mutually_exclusive_group(required=True)
|
||||||
option.add_argument(
|
option.add_argument(
|
||||||
@ -291,6 +268,69 @@ class ListQuota(command.Lister, BaseQuota):
|
|||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
def _get_detailed_quotas(self, parsed_args):
|
||||||
|
project_info = get_project(self.app, parsed_args.project)
|
||||||
|
project = project_info['id']
|
||||||
|
|
||||||
|
quotas = {}
|
||||||
|
|
||||||
|
if parsed_args.compute:
|
||||||
|
quotas.update(
|
||||||
|
get_compute_quotas(
|
||||||
|
self.app,
|
||||||
|
project,
|
||||||
|
detail=parsed_args.detail,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if parsed_args.network:
|
||||||
|
quotas.update(
|
||||||
|
get_network_quotas(
|
||||||
|
self.app,
|
||||||
|
project,
|
||||||
|
detail=parsed_args.detail,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if parsed_args.volume:
|
||||||
|
quotas.update(
|
||||||
|
get_volume_quotas(
|
||||||
|
self.app,
|
||||||
|
parsed_args,
|
||||||
|
detail=parsed_args.detail,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for resource, values in quotas.items():
|
||||||
|
# NOTE(slaweq): there is no detailed quotas info for some resources
|
||||||
|
# and it shouldn't be displayed here
|
||||||
|
if isinstance(values, dict):
|
||||||
|
result.append({
|
||||||
|
'resource': resource,
|
||||||
|
'in_use': values.get('in_use'),
|
||||||
|
'reserved': values.get('reserved'),
|
||||||
|
'limit': values.get('limit'),
|
||||||
|
})
|
||||||
|
|
||||||
|
columns = (
|
||||||
|
'resource',
|
||||||
|
'in_use',
|
||||||
|
'reserved',
|
||||||
|
'limit',
|
||||||
|
)
|
||||||
|
column_headers = (
|
||||||
|
'Resource',
|
||||||
|
'In Use',
|
||||||
|
'Reserved',
|
||||||
|
'Limit',
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
column_headers,
|
||||||
|
(utils.get_dict_properties(s, columns) for s in result),
|
||||||
|
)
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
result = []
|
result = []
|
||||||
project_ids = []
|
project_ids = []
|
||||||
@ -308,6 +348,7 @@ class ListQuota(command.Lister, BaseQuota):
|
|||||||
if parsed_args.compute:
|
if parsed_args.compute:
|
||||||
if parsed_args.detail:
|
if parsed_args.detail:
|
||||||
return self._get_detailed_quotas(parsed_args)
|
return self._get_detailed_quotas(parsed_args)
|
||||||
|
|
||||||
compute_client = self.app.client_manager.compute
|
compute_client = self.app.client_manager.compute
|
||||||
for p in project_ids:
|
for p in project_ids:
|
||||||
try:
|
try:
|
||||||
@ -365,14 +406,15 @@ class ListQuota(command.Lister, BaseQuota):
|
|||||||
'Server Groups',
|
'Server Groups',
|
||||||
'Server Group Members',
|
'Server Group Members',
|
||||||
)
|
)
|
||||||
return (column_headers,
|
return (
|
||||||
(utils.get_dict_properties(
|
column_headers,
|
||||||
s, columns,
|
(utils.get_dict_properties(s, columns) for s in result),
|
||||||
) for s in result))
|
)
|
||||||
|
|
||||||
if parsed_args.volume:
|
if parsed_args.volume:
|
||||||
if parsed_args.detail:
|
if parsed_args.detail:
|
||||||
return self._get_detailed_quotas(parsed_args)
|
return self._get_detailed_quotas(parsed_args)
|
||||||
|
|
||||||
volume_client = self.app.client_manager.volume
|
volume_client = self.app.client_manager.volume
|
||||||
for p in project_ids:
|
for p in project_ids:
|
||||||
try:
|
try:
|
||||||
@ -417,14 +459,16 @@ class ListQuota(command.Lister, BaseQuota):
|
|||||||
'Snapshots',
|
'Snapshots',
|
||||||
'Volumes',
|
'Volumes',
|
||||||
)
|
)
|
||||||
return (column_headers,
|
|
||||||
(utils.get_dict_properties(
|
return (
|
||||||
s, columns,
|
column_headers,
|
||||||
) for s in result))
|
(utils.get_dict_properties(s, columns) for s in result),
|
||||||
|
)
|
||||||
|
|
||||||
if parsed_args.network:
|
if parsed_args.network:
|
||||||
if parsed_args.detail:
|
if parsed_args.detail:
|
||||||
return self._get_detailed_quotas(parsed_args)
|
return self._get_detailed_quotas(parsed_args)
|
||||||
|
|
||||||
client = self.app.client_manager.network
|
client = self.app.client_manager.network
|
||||||
for p in project_ids:
|
for p in project_ids:
|
||||||
try:
|
try:
|
||||||
@ -475,10 +519,11 @@ class ListQuota(command.Lister, BaseQuota):
|
|||||||
'Subnets',
|
'Subnets',
|
||||||
'Subnet Pools'
|
'Subnet Pools'
|
||||||
)
|
)
|
||||||
return (column_headers,
|
|
||||||
(utils.get_dict_properties(
|
return (
|
||||||
s, columns,
|
column_headers,
|
||||||
) for s in result))
|
(utils.get_dict_properties(s, columns) for s in result),
|
||||||
|
)
|
||||||
|
|
||||||
return ((), ())
|
return ((), ())
|
||||||
|
|
||||||
@ -545,14 +590,16 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--force',
|
'--force',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=_('Force quota update (only supported by compute and '
|
help=_(
|
||||||
'network)')
|
'Force quota update (only supported by compute and network)'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--check-limit',
|
'--check-limit',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=_('Check quota limit when updating (only supported by '
|
help=_(
|
||||||
'network)')
|
'Check quota limit when updating (only supported by network)'
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@ -631,14 +678,16 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|||||||
**network_kwargs)
|
**network_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ShowQuota(command.ShowOne, BaseQuota):
|
class ShowQuota(command.ShowOne):
|
||||||
_description = _(
|
_description = _(
|
||||||
"Show quotas for project or class. Specify "
|
"Show quotas for project or class. "
|
||||||
"``--os-compute-api-version 2.50`` or higher to see ``server-groups`` "
|
"Specify ``--os-compute-api-version 2.50`` or higher to see "
|
||||||
"and ``server-group-members`` output for a given quota class.")
|
"``server-groups`` and ``server-group-members`` output for a given "
|
||||||
|
"quota class."
|
||||||
|
)
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super(ShowQuota, self).get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'project',
|
'project',
|
||||||
metavar='<project/class>',
|
metavar='<project/class>',
|
||||||
@ -658,29 +707,40 @@ class ShowQuota(command.ShowOne, BaseQuota):
|
|||||||
dest='default',
|
dest='default',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=False,
|
default=False,
|
||||||
help=_('Show default quotas for <project>')
|
help=_('Show default quotas for <project>'),
|
||||||
)
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
|
project = parsed_args.project
|
||||||
|
|
||||||
compute_client = self.app.client_manager.compute
|
if not parsed_args.quota_class:
|
||||||
volume_client = self.app.client_manager.volume
|
project_info = get_project(self.app, parsed_args.project)
|
||||||
# NOTE(dtroyer): These quota API calls do not validate the project
|
project = project_info['id']
|
||||||
# or class arguments and return what appears to be
|
|
||||||
# the default quota values if the project or class
|
# NOTE(dtroyer): These quota API calls do not validate the project or
|
||||||
# does not exist. If this is determined to be the
|
# class arguments and return what appears to be the default quota
|
||||||
# intended behaviour of the API we will validate
|
# values if the project or class does not exist. If this is determined
|
||||||
# the argument with Identity ourselves later.
|
# to be the intended behaviour of the API we will validate the argument
|
||||||
compute_quota_info = self.get_compute_quota(compute_client,
|
# with Identity ourselves later.
|
||||||
parsed_args)
|
compute_quota_info = get_compute_quotas(
|
||||||
volume_quota_info = self.get_volume_quota(volume_client,
|
self.app,
|
||||||
parsed_args)
|
project,
|
||||||
network_quota_info = self.get_network_quota(parsed_args)
|
quota_class=parsed_args.quota_class,
|
||||||
# NOTE(reedip): Remove the below check once requirement for
|
default=parsed_args.default,
|
||||||
# Openstack SDK is fixed to version 0.9.12 and above
|
)
|
||||||
if type(network_quota_info) is not dict:
|
volume_quota_info = get_volume_quotas(
|
||||||
network_quota_info = network_quota_info.to_dict()
|
self.app,
|
||||||
|
project,
|
||||||
|
quota_class=parsed_args.quota_class,
|
||||||
|
default=parsed_args.default,
|
||||||
|
)
|
||||||
|
network_quota_info = get_network_quotas(
|
||||||
|
self.app,
|
||||||
|
project,
|
||||||
|
quota_class=parsed_args.quota_class,
|
||||||
|
default=parsed_args.default,
|
||||||
|
)
|
||||||
|
|
||||||
info = {}
|
info = {}
|
||||||
info.update(compute_quota_info)
|
info.update(compute_quota_info)
|
||||||
@ -693,20 +753,27 @@ class ShowQuota(command.ShowOne, BaseQuota):
|
|||||||
# neutron is enabled, quotas of these three resources
|
# neutron is enabled, quotas of these three resources
|
||||||
# in nova will be replaced by neutron's.
|
# in nova will be replaced by neutron's.
|
||||||
for k, v in itertools.chain(
|
for k, v in itertools.chain(
|
||||||
COMPUTE_QUOTAS.items(), NOVA_NETWORK_QUOTAS.items(),
|
COMPUTE_QUOTAS.items(),
|
||||||
VOLUME_QUOTAS.items(), NETWORK_QUOTAS.items()):
|
NOVA_NETWORK_QUOTAS.items(),
|
||||||
|
VOLUME_QUOTAS.items(),
|
||||||
|
NETWORK_QUOTAS.items(),
|
||||||
|
):
|
||||||
if not k == v and info.get(k) is not None:
|
if not k == v and info.get(k) is not None:
|
||||||
info[v] = info[k]
|
info[v] = info[k]
|
||||||
info.pop(k)
|
info.pop(k)
|
||||||
|
|
||||||
# Handle project ID special as it only appears in output
|
# Remove the 'location' field for resources from openstacksdk
|
||||||
if 'id' in info:
|
if 'location' in info:
|
||||||
|
del info['location']
|
||||||
|
|
||||||
|
# Handle class or project ID specially as they only appear in output
|
||||||
|
if parsed_args.quota_class:
|
||||||
|
info.pop('id', None)
|
||||||
|
elif 'id' in info:
|
||||||
info['project'] = info.pop('id')
|
info['project'] = info.pop('id')
|
||||||
if 'project_id' in info:
|
if 'project_id' in info:
|
||||||
del info['project_id']
|
del info['project_id']
|
||||||
project_info = self._get_project(parsed_args)
|
info['project_name'] = project_info['name']
|
||||||
project_name = project_info['name']
|
|
||||||
info['project_name'] = project_name
|
|
||||||
|
|
||||||
return zip(*sorted(info.items()))
|
return zip(*sorted(info.items()))
|
||||||
|
|
||||||
|
@ -1166,29 +1166,6 @@ class TestQuotaShow(TestQuota):
|
|||||||
)
|
)
|
||||||
self.assertNotCalled(self.network.get_quota_default)
|
self.assertNotCalled(self.network.get_quota_default)
|
||||||
|
|
||||||
def test_network_quota_show_remove_empty(self):
|
|
||||||
arglist = [
|
|
||||||
self.projects[0].name,
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('project', self.projects[0].name),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
# First check that all regular values are returned
|
|
||||||
result = self.cmd.get_network_quota(parsed_args)
|
|
||||||
self.assertEqual(len(network_fakes.QUOTA), len(result))
|
|
||||||
|
|
||||||
# set 1 of the values to None, and verify it is not returned
|
|
||||||
orig_get_quota = self.network.get_quota
|
|
||||||
network_quotas = copy.copy(network_fakes.QUOTA)
|
|
||||||
network_quotas['healthmonitor'] = None
|
|
||||||
self.network.get_quota = mock.Mock(return_value=network_quotas)
|
|
||||||
result = self.cmd.get_network_quota(parsed_args)
|
|
||||||
self.assertEqual(len(network_fakes.QUOTA) - 1, len(result))
|
|
||||||
# Go back to default mock
|
|
||||||
self.network.get_quota = orig_get_quota
|
|
||||||
|
|
||||||
|
|
||||||
class TestQuotaDelete(TestQuota):
|
class TestQuotaDelete(TestQuota):
|
||||||
"""Test cases for quota delete command"""
|
"""Test cases for quota delete command"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user