Merge "quota: Remove deprecated quota options"
This commit is contained in:
commit
45ac2b62fb
@ -11,7 +11,6 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
|
||||||
|
|
||||||
"""Quota action implementations"""
|
"""Quota action implementations"""
|
||||||
|
|
||||||
@ -130,18 +129,12 @@ def get_compute_quotas(
|
|||||||
app,
|
app,
|
||||||
project_id,
|
project_id,
|
||||||
*,
|
*,
|
||||||
quota_class=False,
|
|
||||||
detail=False,
|
detail=False,
|
||||||
default=False,
|
default=False,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
client = app.client_manager.compute
|
client = app.client_manager.compute
|
||||||
if quota_class:
|
if default:
|
||||||
# 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)
|
quota = client.quotas.defaults(project_id)
|
||||||
else:
|
else:
|
||||||
quota = client.quotas.get(project_id, detail=detail)
|
quota = client.quotas.get(project_id, detail=detail)
|
||||||
@ -156,15 +149,12 @@ def get_volume_quotas(
|
|||||||
app,
|
app,
|
||||||
project_id,
|
project_id,
|
||||||
*,
|
*,
|
||||||
quota_class=False,
|
|
||||||
detail=False,
|
detail=False,
|
||||||
default=False,
|
default=False,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
client = app.client_manager.volume
|
client = app.client_manager.volume
|
||||||
if quota_class:
|
if default:
|
||||||
quota = client.quota_classes.get(project_id)
|
|
||||||
elif default:
|
|
||||||
quota = client.quotas.defaults(project_id)
|
quota = client.quotas.defaults(project_id)
|
||||||
else:
|
else:
|
||||||
quota = client.quotas.get(project_id, usage=detail)
|
quota = client.quotas.get(project_id, usage=detail)
|
||||||
@ -180,7 +170,6 @@ def get_network_quotas(
|
|||||||
app,
|
app,
|
||||||
project_id,
|
project_id,
|
||||||
*,
|
*,
|
||||||
quota_class=False,
|
|
||||||
detail=False,
|
detail=False,
|
||||||
default=False,
|
default=False,
|
||||||
):
|
):
|
||||||
@ -207,11 +196,6 @@ def get_network_quotas(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# neutron doesn't have the concept of quota classes and if we're using
|
|
||||||
# nova-network we already fetched this
|
|
||||||
if quota_class:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
# we have nothing to return if we are not using neutron
|
# we have nothing to return if we are not using neutron
|
||||||
if not app.client_manager.is_network_endpoint_enabled():
|
if not app.client_manager.is_network_endpoint_enabled():
|
||||||
return {}
|
return {}
|
||||||
@ -227,34 +211,14 @@ def get_network_quotas(
|
|||||||
|
|
||||||
|
|
||||||
class ListQuota(command.Lister):
|
class ListQuota(command.Lister):
|
||||||
_description = _(
|
"""List quotas for all projects with non-default quota values.
|
||||||
"List quotas for all projects with non-default quota values or "
|
|
||||||
"list detailed quota information for requested project"
|
Empty output means all projects are using default quotas, which can be
|
||||||
)
|
inspected with 'openstack quota show --default'.
|
||||||
|
"""
|
||||||
|
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super().get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
# TODO(stephenfin): Remove in OSC 8.0
|
|
||||||
parser.add_argument(
|
|
||||||
'--project',
|
|
||||||
metavar='<project>',
|
|
||||||
help=_(
|
|
||||||
"**Deprecated** List quotas for this project <project> "
|
|
||||||
"(name or ID). "
|
|
||||||
"Use 'quota show' instead."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
# TODO(stephenfin): Remove in OSC 8.0
|
|
||||||
parser.add_argument(
|
|
||||||
'--detail',
|
|
||||||
dest='detail',
|
|
||||||
action='store_true',
|
|
||||||
default=False,
|
|
||||||
help=_(
|
|
||||||
"**Deprecated** Show details about quotas usage. "
|
|
||||||
"Use 'quota show --usage' instead."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
option = parser.add_mutually_exclusive_group(required=True)
|
option = parser.add_mutually_exclusive_group(required=True)
|
||||||
option.add_argument(
|
option.add_argument(
|
||||||
'--compute',
|
'--compute',
|
||||||
@ -276,102 +240,13 @@ class ListQuota(command.Lister):
|
|||||||
)
|
)
|
||||||
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):
|
||||||
if parsed_args.detail:
|
|
||||||
msg = _(
|
|
||||||
"The --detail option has been deprecated. "
|
|
||||||
"Use 'openstack quota show --usage' instead."
|
|
||||||
)
|
|
||||||
self.log.warning(msg)
|
|
||||||
elif parsed_args.project: # elif to avoid being too noisy
|
|
||||||
msg = _(
|
|
||||||
"The --project option has been deprecated. "
|
|
||||||
"Use 'openstack quota show' instead."
|
|
||||||
)
|
|
||||||
self.log.warning(msg)
|
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
project_ids = []
|
project_ids = [
|
||||||
if parsed_args.project is None:
|
p.id for p in self.app.client_manager.identity.projects.list()
|
||||||
for p in self.app.client_manager.identity.projects.list():
|
]
|
||||||
project_ids.append(getattr(p, 'id', ''))
|
|
||||||
else:
|
|
||||||
identity_client = self.app.client_manager.identity
|
|
||||||
project = utils.find_resource(
|
|
||||||
identity_client.projects,
|
|
||||||
parsed_args.project,
|
|
||||||
)
|
|
||||||
project_ids.append(getattr(project, 'id', ''))
|
|
||||||
|
|
||||||
if parsed_args.compute:
|
if parsed_args.compute:
|
||||||
if parsed_args.detail:
|
|
||||||
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:
|
||||||
@ -434,9 +309,6 @@ class ListQuota(command.Lister):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if parsed_args.volume:
|
if parsed_args.volume:
|
||||||
if parsed_args.detail:
|
|
||||||
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:
|
||||||
@ -488,9 +360,6 @@ class ListQuota(command.Lister):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if parsed_args.network:
|
if parsed_args.network:
|
||||||
if parsed_args.detail:
|
|
||||||
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:
|
||||||
@ -728,22 +597,24 @@ class SetQuota(common.NetDetectionMixin, command.Command):
|
|||||||
"Network quotas are ignored since quota classes are not "
|
"Network quotas are ignored since quota classes are not "
|
||||||
"supported."
|
"supported."
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
project = utils.find_resource(
|
|
||||||
identity_client.projects,
|
|
||||||
parsed_args.project,
|
|
||||||
).id
|
|
||||||
|
|
||||||
if compute_kwargs:
|
return
|
||||||
compute_client.quotas.update(project, **compute_kwargs)
|
|
||||||
if volume_kwargs:
|
project = utils.find_resource(
|
||||||
volume_client.quotas.update(project, **volume_kwargs)
|
identity_client.projects,
|
||||||
if (
|
parsed_args.project,
|
||||||
network_kwargs
|
).id
|
||||||
and self.app.client_manager.is_network_endpoint_enabled()
|
|
||||||
):
|
if compute_kwargs:
|
||||||
network_client = self.app.client_manager.network
|
compute_client.quotas.update(project, **compute_kwargs)
|
||||||
network_client.update_quota(project, **network_kwargs)
|
if volume_kwargs:
|
||||||
|
volume_client.quotas.update(project, **volume_kwargs)
|
||||||
|
if (
|
||||||
|
network_kwargs
|
||||||
|
and self.app.client_manager.is_network_endpoint_enabled()
|
||||||
|
):
|
||||||
|
network_client = self.app.client_manager.network
|
||||||
|
network_client.update_quota(project, **network_kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ShowQuota(command.Lister):
|
class ShowQuota(command.Lister):
|
||||||
@ -758,29 +629,14 @@ and ``server-group-members`` output for a given quota class."""
|
|||||||
parser = super().get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'project',
|
'project',
|
||||||
metavar='<project/class>',
|
metavar='<project>',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
help=_(
|
help=_(
|
||||||
'Show quotas for this project or class (name or ID) '
|
'Show quotas for this project (name or ID) '
|
||||||
'(defaults to current project)'
|
'(defaults to current project)'
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
type_group = parser.add_mutually_exclusive_group()
|
type_group = parser.add_mutually_exclusive_group()
|
||||||
# TODO(stephenfin): Remove in OSC 8.0
|
|
||||||
type_group.add_argument(
|
|
||||||
'--class',
|
|
||||||
dest='quota_class',
|
|
||||||
action='store_true',
|
|
||||||
default=False,
|
|
||||||
help=_(
|
|
||||||
'**Deprecated** Show quotas for <class>. '
|
|
||||||
'Deprecated as quota classes were never fully implemented '
|
|
||||||
'and only the default class is supported. '
|
|
||||||
'Use --default instead which is also supported by the network '
|
|
||||||
'service. '
|
|
||||||
'(compute and volume only)'
|
|
||||||
),
|
|
||||||
)
|
|
||||||
type_group.add_argument(
|
type_group.add_argument(
|
||||||
'--default',
|
'--default',
|
||||||
dest='default',
|
dest='default',
|
||||||
@ -832,20 +688,8 @@ and ``server-group-members`` output for a given quota class."""
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
project = parsed_args.project
|
project_info = get_project(self.app, parsed_args.project)
|
||||||
|
project = project_info['id']
|
||||||
if parsed_args.quota_class:
|
|
||||||
msg = _(
|
|
||||||
"The '--class' option has been deprecated. Quota classes were "
|
|
||||||
"never fully implemented and the compute and volume services "
|
|
||||||
"only support a single 'default' quota class while the "
|
|
||||||
"network service does not support quota classes at all. "
|
|
||||||
"Please use 'openstack quota show --default' instead."
|
|
||||||
)
|
|
||||||
self.log.warning(msg)
|
|
||||||
else:
|
|
||||||
project_info = get_project(self.app, parsed_args.project)
|
|
||||||
project = project_info['id']
|
|
||||||
|
|
||||||
compute_quota_info = {}
|
compute_quota_info = {}
|
||||||
volume_quota_info = {}
|
volume_quota_info = {}
|
||||||
@ -861,7 +705,6 @@ and ``server-group-members`` output for a given quota class."""
|
|||||||
self.app,
|
self.app,
|
||||||
project,
|
project,
|
||||||
detail=parsed_args.usage,
|
detail=parsed_args.usage,
|
||||||
quota_class=parsed_args.quota_class,
|
|
||||||
default=parsed_args.default,
|
default=parsed_args.default,
|
||||||
)
|
)
|
||||||
if parsed_args.service in {'all', 'volume'}:
|
if parsed_args.service in {'all', 'volume'}:
|
||||||
@ -869,7 +712,6 @@ and ``server-group-members`` output for a given quota class."""
|
|||||||
self.app,
|
self.app,
|
||||||
project,
|
project,
|
||||||
detail=parsed_args.usage,
|
detail=parsed_args.usage,
|
||||||
quota_class=parsed_args.quota_class,
|
|
||||||
default=parsed_args.default,
|
default=parsed_args.default,
|
||||||
)
|
)
|
||||||
if parsed_args.service in {'all', 'network'}:
|
if parsed_args.service in {'all', 'network'}:
|
||||||
@ -877,7 +719,6 @@ and ``server-group-members`` output for a given quota class."""
|
|||||||
self.app,
|
self.app,
|
||||||
project,
|
project,
|
||||||
detail=parsed_args.usage,
|
detail=parsed_args.usage,
|
||||||
quota_class=parsed_args.quota_class,
|
|
||||||
default=parsed_args.default,
|
default=parsed_args.default,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,40 +39,6 @@ class QuotaTests(base.TestCase):
|
|||||||
cls.openstack(f'project delete {cls.PROJECT_NAME}')
|
cls.openstack(f'project delete {cls.PROJECT_NAME}')
|
||||||
super().tearDownClass()
|
super().tearDownClass()
|
||||||
|
|
||||||
def test_quota_list_details_compute(self):
|
|
||||||
expected_headers = ["Resource", "In Use", "Reserved", "Limit"]
|
|
||||||
cmd_output = self.openstack(
|
|
||||||
'quota list --detail --compute',
|
|
||||||
parse_output=True,
|
|
||||||
)
|
|
||||||
self.assertIsNotNone(cmd_output)
|
|
||||||
resources = []
|
|
||||||
for row in cmd_output:
|
|
||||||
row_headers = [str(r) for r in row.keys()]
|
|
||||||
self.assertEqual(sorted(expected_headers), sorted(row_headers))
|
|
||||||
resources.append(row['Resource'])
|
|
||||||
# Ensure that returned quota is compute quota
|
|
||||||
self.assertIn("instances", resources)
|
|
||||||
# and that there is no network quota here
|
|
||||||
self.assertNotIn("networks", resources)
|
|
||||||
|
|
||||||
def test_quota_list_details_network(self):
|
|
||||||
expected_headers = ["Resource", "In Use", "Reserved", "Limit"]
|
|
||||||
cmd_output = self.openstack(
|
|
||||||
'quota list --detail --network',
|
|
||||||
parse_output=True,
|
|
||||||
)
|
|
||||||
self.assertIsNotNone(cmd_output)
|
|
||||||
resources = []
|
|
||||||
for row in cmd_output:
|
|
||||||
row_headers = [str(r) for r in row.keys()]
|
|
||||||
self.assertEqual(sorted(expected_headers), sorted(row_headers))
|
|
||||||
resources.append(row['Resource'])
|
|
||||||
# Ensure that returned quota is network quota
|
|
||||||
self.assertIn("networks", resources)
|
|
||||||
# and that there is no compute quota here
|
|
||||||
self.assertNotIn("instances", resources)
|
|
||||||
|
|
||||||
def test_quota_list_network_option(self):
|
def test_quota_list_network_option(self):
|
||||||
if not self.haz_network:
|
if not self.haz_network:
|
||||||
self.skipTest("No Network service present")
|
self.skipTest("No Network service present")
|
||||||
@ -155,41 +121,23 @@ class QuotaTests(base.TestCase):
|
|||||||
if self.haz_network:
|
if self.haz_network:
|
||||||
self.assertTrue(cmd_output["routers"] >= 0)
|
self.assertTrue(cmd_output["routers"] >= 0)
|
||||||
|
|
||||||
def test_quota_set_class(self):
|
def test_quota_set_default(self):
|
||||||
self.openstack(
|
self.openstack(
|
||||||
'quota set --key-pairs 33 --snapshots 43 ' + '--class default'
|
'quota set --key-pairs 33 --snapshots 43 --class default'
|
||||||
)
|
)
|
||||||
cmd_output = self.openstack(
|
cmd_output = self.openstack(
|
||||||
'quota show --class default',
|
'quota show --default',
|
||||||
parse_output=True,
|
parse_output=True,
|
||||||
)
|
)
|
||||||
self.assertIsNotNone(cmd_output)
|
self.assertIsNotNone(cmd_output)
|
||||||
cmd_output = {x['Resource']: x['Limit'] for x in cmd_output}
|
cmd_output = {x['Resource']: x['Limit'] for x in cmd_output}
|
||||||
self.assertEqual(
|
self.assertEqual(33, cmd_output["key-pairs"])
|
||||||
33,
|
self.assertEqual(43, cmd_output["snapshots"])
|
||||||
cmd_output["key-pairs"],
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
43,
|
|
||||||
cmd_output["snapshots"],
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check default quota class
|
|
||||||
cmd_output = self.openstack(
|
|
||||||
'quota show --class',
|
|
||||||
parse_output=True,
|
|
||||||
)
|
|
||||||
self.assertIsNotNone(cmd_output)
|
|
||||||
# We don't necessarily know the default quotas, we're checking the
|
|
||||||
# returned attributes
|
|
||||||
cmd_output = {x['Resource']: x['Limit'] for x in cmd_output}
|
|
||||||
self.assertTrue(cmd_output["key-pairs"] >= 0)
|
|
||||||
self.assertTrue(cmd_output["snapshots"] >= 0)
|
|
||||||
|
|
||||||
def _restore_quota_limit(self, resource, limit, project):
|
def _restore_quota_limit(self, resource, limit, project):
|
||||||
self.openstack(f'quota set --{resource} {limit} {project}')
|
self.openstack(f'quota set --{resource} {limit} {project}')
|
||||||
|
|
||||||
def test_quota_network_set_with_no_force(self):
|
def test_quota_set_network_with_no_force(self):
|
||||||
if not self.haz_network:
|
if not self.haz_network:
|
||||||
self.skipTest('No Network service present')
|
self.skipTest('No Network service present')
|
||||||
if not self.is_extension_enabled('quota-check-limit'):
|
if not self.is_extension_enabled('quota-check-limit'):
|
||||||
@ -227,7 +175,7 @@ class QuotaTests(base.TestCase):
|
|||||||
'quota set --networks 1 --no-force ' + self.PROJECT_NAME,
|
'quota set --networks 1 --no-force ' + self.PROJECT_NAME,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_quota_network_set_with_force(self):
|
def test_quota_set_network_with_force(self):
|
||||||
self.skipTest('story 2010110')
|
self.skipTest('story 2010110')
|
||||||
if not self.haz_network:
|
if not self.haz_network:
|
||||||
self.skipTest('No Network service present')
|
self.skipTest('No Network service present')
|
||||||
@ -274,3 +222,37 @@ class QuotaTests(base.TestCase):
|
|||||||
)
|
)
|
||||||
self.assertIsNotNone(cmd_output)
|
self.assertIsNotNone(cmd_output)
|
||||||
self.assertEqual(1, cmd_output[0]['Networks'])
|
self.assertEqual(1, cmd_output[0]['Networks'])
|
||||||
|
|
||||||
|
def test_quota_show(self):
|
||||||
|
expected_headers = ["Resource", "Limit"]
|
||||||
|
cmd_output = self.openstack(
|
||||||
|
'quota show',
|
||||||
|
parse_output=True,
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(cmd_output)
|
||||||
|
resources = []
|
||||||
|
for row in cmd_output:
|
||||||
|
row_headers = [str(r) for r in row.keys()]
|
||||||
|
self.assertEqual(sorted(expected_headers), sorted(row_headers))
|
||||||
|
resources.append(row['Resource'])
|
||||||
|
# Ensure that returned quota has network quota...
|
||||||
|
self.assertIn("networks", resources)
|
||||||
|
# ...and compute quota
|
||||||
|
self.assertIn("instances", resources)
|
||||||
|
|
||||||
|
def test_quota_show_usage_option(self):
|
||||||
|
expected_headers = ["Resource", "Limit", "In Use", "Reserved"]
|
||||||
|
cmd_output = self.openstack(
|
||||||
|
'quota show --usage',
|
||||||
|
parse_output=True,
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(cmd_output)
|
||||||
|
resources = []
|
||||||
|
for row in cmd_output:
|
||||||
|
row_headers = [str(r) for r in row.keys()]
|
||||||
|
self.assertEqual(sorted(expected_headers), sorted(row_headers))
|
||||||
|
resources.append(row['Resource'])
|
||||||
|
# Ensure that returned quota has network quota...
|
||||||
|
self.assertIn("networks", resources)
|
||||||
|
# ...and compute quota
|
||||||
|
self.assertIn("instances", resources)
|
||||||
|
@ -189,115 +189,6 @@ class TestQuotaList(TestQuota):
|
|||||||
|
|
||||||
self.cmd = quota.ListQuota(self.app, None)
|
self.cmd = quota.ListQuota(self.app, None)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _get_detailed_reference_data(quota):
|
|
||||||
reference_data = []
|
|
||||||
for name, values in quota.to_dict().items():
|
|
||||||
if type(values) is dict:
|
|
||||||
if 'used' in values:
|
|
||||||
# For network quota it's "used" key instead of "in_use"
|
|
||||||
in_use = values['used']
|
|
||||||
else:
|
|
||||||
in_use = values['in_use']
|
|
||||||
resource_values = [in_use, values['reserved'], values['limit']]
|
|
||||||
reference_data.append(tuple([name] + resource_values))
|
|
||||||
return reference_data
|
|
||||||
|
|
||||||
def test_quota_list_details_compute(self):
|
|
||||||
detailed_quota = compute_fakes.create_one_comp_detailed_quota()
|
|
||||||
|
|
||||||
detailed_column_header = (
|
|
||||||
'Resource',
|
|
||||||
'In Use',
|
|
||||||
'Reserved',
|
|
||||||
'Limit',
|
|
||||||
)
|
|
||||||
detailed_reference_data = self._get_detailed_reference_data(
|
|
||||||
detailed_quota
|
|
||||||
)
|
|
||||||
|
|
||||||
self.compute_client.quotas.get = mock.Mock(return_value=detailed_quota)
|
|
||||||
|
|
||||||
arglist = [
|
|
||||||
'--detail',
|
|
||||||
'--compute',
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('detail', True),
|
|
||||||
('compute', True),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
|
||||||
ret_quotas = list(data)
|
|
||||||
|
|
||||||
self.assertEqual(detailed_column_header, columns)
|
|
||||||
self.assertEqual(sorted(detailed_reference_data), sorted(ret_quotas))
|
|
||||||
|
|
||||||
def test_quota_list_details_network(self):
|
|
||||||
detailed_quota = (
|
|
||||||
network_fakes.FakeQuota.create_one_net_detailed_quota()
|
|
||||||
)
|
|
||||||
|
|
||||||
detailed_column_header = (
|
|
||||||
'Resource',
|
|
||||||
'In Use',
|
|
||||||
'Reserved',
|
|
||||||
'Limit',
|
|
||||||
)
|
|
||||||
detailed_reference_data = self._get_detailed_reference_data(
|
|
||||||
detailed_quota
|
|
||||||
)
|
|
||||||
|
|
||||||
self.network_client.get_quota = mock.Mock(return_value=detailed_quota)
|
|
||||||
|
|
||||||
arglist = [
|
|
||||||
'--detail',
|
|
||||||
'--network',
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('detail', True),
|
|
||||||
('network', True),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
|
||||||
ret_quotas = list(data)
|
|
||||||
|
|
||||||
self.assertEqual(detailed_column_header, columns)
|
|
||||||
self.assertEqual(sorted(detailed_reference_data), sorted(ret_quotas))
|
|
||||||
|
|
||||||
def test_quota_list_details_volume(self):
|
|
||||||
detailed_quota = volume_fakes.create_one_detailed_quota()
|
|
||||||
|
|
||||||
detailed_column_header = (
|
|
||||||
'Resource',
|
|
||||||
'In Use',
|
|
||||||
'Reserved',
|
|
||||||
'Limit',
|
|
||||||
)
|
|
||||||
detailed_reference_data = self._get_detailed_reference_data(
|
|
||||||
detailed_quota
|
|
||||||
)
|
|
||||||
|
|
||||||
self.volume_client.quotas.get = mock.Mock(return_value=detailed_quota)
|
|
||||||
|
|
||||||
arglist = [
|
|
||||||
'--detail',
|
|
||||||
'--volume',
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('detail', True),
|
|
||||||
('volume', True),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
|
||||||
ret_quotas = list(data)
|
|
||||||
|
|
||||||
self.assertEqual(detailed_column_header, columns)
|
|
||||||
self.assertEqual(sorted(detailed_reference_data), sorted(ret_quotas))
|
|
||||||
|
|
||||||
def test_quota_list_compute(self):
|
def test_quota_list_compute(self):
|
||||||
# Two projects with non-default quotas
|
# Two projects with non-default quotas
|
||||||
self.compute_client.quotas.get = mock.Mock(
|
self.compute_client.quotas.get = mock.Mock(
|
||||||
@ -414,30 +305,6 @@ class TestQuotaList(TestQuota):
|
|||||||
parsed_args,
|
parsed_args,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_quota_list_compute_by_project(self):
|
|
||||||
# Two projects with non-default quotas
|
|
||||||
self.compute_client.quotas.get = mock.Mock(
|
|
||||||
side_effect=self.compute_quotas,
|
|
||||||
)
|
|
||||||
|
|
||||||
arglist = [
|
|
||||||
'--compute',
|
|
||||||
'--project',
|
|
||||||
self.projects[0].name,
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('compute', True),
|
|
||||||
('project', self.projects[0].name),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
|
||||||
ret_quotas = list(data)
|
|
||||||
|
|
||||||
self.assertEqual(self.compute_column_header, columns)
|
|
||||||
self.assertEqual(self.compute_reference_data, ret_quotas[0])
|
|
||||||
self.assertEqual(1, len(ret_quotas))
|
|
||||||
|
|
||||||
def test_quota_list_network(self):
|
def test_quota_list_network(self):
|
||||||
# Two projects with non-default quotas
|
# Two projects with non-default quotas
|
||||||
self.network_client.get_quota = mock.Mock(
|
self.network_client.get_quota = mock.Mock(
|
||||||
@ -507,30 +374,6 @@ class TestQuotaList(TestQuota):
|
|||||||
self.assertEqual(self.network_reference_data, ret_quotas[0])
|
self.assertEqual(self.network_reference_data, ret_quotas[0])
|
||||||
self.assertEqual(1, len(ret_quotas))
|
self.assertEqual(1, len(ret_quotas))
|
||||||
|
|
||||||
def test_quota_list_network_by_project(self):
|
|
||||||
# Two projects with non-default quotas
|
|
||||||
self.network_client.get_quota = mock.Mock(
|
|
||||||
side_effect=self.network_quotas,
|
|
||||||
)
|
|
||||||
|
|
||||||
arglist = [
|
|
||||||
'--network',
|
|
||||||
'--project',
|
|
||||||
self.projects[0].name,
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('network', True),
|
|
||||||
('project', self.projects[0].name),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
|
||||||
ret_quotas = list(data)
|
|
||||||
|
|
||||||
self.assertEqual(self.network_column_header, columns)
|
|
||||||
self.assertEqual(self.network_reference_data, ret_quotas[0])
|
|
||||||
self.assertEqual(1, len(ret_quotas))
|
|
||||||
|
|
||||||
def test_quota_list_volume(self):
|
def test_quota_list_volume(self):
|
||||||
# Two projects with non-default quotas
|
# Two projects with non-default quotas
|
||||||
self.volume_client.quotas.get = mock.Mock(
|
self.volume_client.quotas.get = mock.Mock(
|
||||||
@ -600,30 +443,6 @@ class TestQuotaList(TestQuota):
|
|||||||
self.assertEqual(self.volume_reference_data, ret_quotas[0])
|
self.assertEqual(self.volume_reference_data, ret_quotas[0])
|
||||||
self.assertEqual(1, len(ret_quotas))
|
self.assertEqual(1, len(ret_quotas))
|
||||||
|
|
||||||
def test_quota_list_volume_by_project(self):
|
|
||||||
# Two projects with non-default quotas
|
|
||||||
self.volume_client.quotas.get = mock.Mock(
|
|
||||||
side_effect=self.volume_quotas,
|
|
||||||
)
|
|
||||||
|
|
||||||
arglist = [
|
|
||||||
'--volume',
|
|
||||||
'--project',
|
|
||||||
self.projects[0].name,
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('volume', True),
|
|
||||||
('project', self.projects[0].name),
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
|
||||||
ret_quotas = list(data)
|
|
||||||
|
|
||||||
self.assertEqual(self.volume_column_header, columns)
|
|
||||||
self.assertEqual(self.volume_reference_data, ret_quotas[0])
|
|
||||||
self.assertEqual(1, len(ret_quotas))
|
|
||||||
|
|
||||||
|
|
||||||
class TestQuotaSet(TestQuota):
|
class TestQuotaSet(TestQuota):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -1227,25 +1046,6 @@ class TestQuotaShow(TestQuota):
|
|||||||
)
|
)
|
||||||
self.assertNotCalled(self.network_client.get_quota)
|
self.assertNotCalled(self.network_client.get_quota)
|
||||||
|
|
||||||
def test_quota_show__with_class(self):
|
|
||||||
arglist = [
|
|
||||||
'--class',
|
|
||||||
'default',
|
|
||||||
]
|
|
||||||
verifylist = [
|
|
||||||
('quota_class', True),
|
|
||||||
('project', 'default'), # project is actually a class here
|
|
||||||
]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
||||||
|
|
||||||
self.cmd.take_action(parsed_args)
|
|
||||||
|
|
||||||
self.compute_quotas_class_mock.get.assert_called_once_with('default')
|
|
||||||
self.volume_quotas_class_mock.get.assert_called_once_with('default')
|
|
||||||
# neutron doesn't have the concept of quota classes
|
|
||||||
self.assertNotCalled(self.network_client.get_quota)
|
|
||||||
self.assertNotCalled(self.network_client.get_quota_default)
|
|
||||||
|
|
||||||
def test_quota_show__with_usage(self):
|
def test_quota_show__with_usage(self):
|
||||||
# update mocks to return detailed quota instead
|
# update mocks to return detailed quota instead
|
||||||
self.compute_quota = compute_fakes.create_one_comp_detailed_quota()
|
self.compute_quota = compute_fakes.create_one_comp_detailed_quota()
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
The ``--class`` options of the ``quota show`` command, which was deprecated
|
||||||
|
in 6.1.0 (Antelope), has now been removed in favour of the ``--default``
|
||||||
|
option. Quota classes were never fully implemented and the compute and
|
||||||
|
volume services only support a single ``default`` quota class while the
|
||||||
|
network service does not support quota classes at all.
|
Loading…
x
Reference in New Issue
Block a user