Change-Id: Id6ca5075bd11765f00b62b44f91635ef68205175 Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
471 lines
16 KiB
Python
471 lines
16 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from osc_lib.command import command
|
|
from osc_lib import exceptions
|
|
from osc_lib import utils
|
|
|
|
from manilaclient import api_versions
|
|
from manilaclient.common._i18n import _
|
|
|
|
|
|
class QuotaSet(command.Command):
|
|
"""Set quotas for a project or project/user or project/share-type.
|
|
|
|
It can be used to set the default class for all projects.
|
|
"""
|
|
|
|
_description = _(
|
|
"Set Quota for a project, or project/user or "
|
|
"project/share-type or a class."
|
|
)
|
|
|
|
def get_parser(self, prog_name):
|
|
parser = super().get_parser(prog_name)
|
|
quota_type = parser.add_mutually_exclusive_group()
|
|
parser.add_argument(
|
|
'project',
|
|
metavar='<project/class>',
|
|
help=_("A project (name/ID) or a class (e.g.: default)."),
|
|
)
|
|
quota_type.add_argument(
|
|
'--class',
|
|
dest='quota_class',
|
|
action='store_true',
|
|
default=False,
|
|
help=_(
|
|
"Update class quota to all projects. "
|
|
"Mutually exclusive with '--user' and '--share-type'."
|
|
),
|
|
)
|
|
quota_type.add_argument(
|
|
'--user',
|
|
metavar='<user>',
|
|
default=None,
|
|
help=_(
|
|
"Name or ID of a user to set the quotas for. "
|
|
"Mutually exclusive with '--share-type' and '--class'."
|
|
),
|
|
)
|
|
quota_type.add_argument(
|
|
'--share-type',
|
|
metavar='<share-type>',
|
|
type=str,
|
|
default=None,
|
|
help=_(
|
|
"Name or ID of a share type to set the quotas for. "
|
|
"Mutually exclusive with '--user' and '--class'. "
|
|
"Available only for microversion >= 2.39"
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--shares',
|
|
metavar='<shares>',
|
|
type=int,
|
|
default=None,
|
|
help=_('New value for the "shares" quota.'),
|
|
)
|
|
parser.add_argument(
|
|
'--snapshots',
|
|
metavar='<snapshots>',
|
|
type=int,
|
|
default=None,
|
|
help=_('New value for the "snapshots" quota.'),
|
|
)
|
|
parser.add_argument(
|
|
'--gigabytes',
|
|
metavar='<gigabytes>',
|
|
type=int,
|
|
default=None,
|
|
help=_('New value for the "gigabytes" quota.'),
|
|
)
|
|
parser.add_argument(
|
|
'--snapshot-gigabytes',
|
|
metavar='<snapshot-gigabytes>',
|
|
type=int,
|
|
default=None,
|
|
help=_('New value for the "snapshot-gigabytes" quota.'),
|
|
)
|
|
parser.add_argument(
|
|
'--share-networks',
|
|
metavar='<share-networks>',
|
|
type=int,
|
|
default=None,
|
|
help=_('New value for the "share-networks" quota.'),
|
|
)
|
|
parser.add_argument(
|
|
'--share-groups',
|
|
metavar='<share-groups>',
|
|
type=int,
|
|
default=None,
|
|
help=_(
|
|
'New value for the "share-groups" quota. '
|
|
'Available only for microversion >= 2.40'
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--share-group-snapshots',
|
|
metavar='<share-group-snapshots>',
|
|
type=int,
|
|
default=None,
|
|
help=_(
|
|
'New value for the "share-group-snapshots" quota. '
|
|
'Available only for microversion >= 2.40'
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--share-replicas',
|
|
metavar='<share-replicas>',
|
|
type=int,
|
|
default=None,
|
|
help=_(
|
|
"Number of share replicas. "
|
|
"Available only for microversion >= 2.53"
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--replica-gigabytes',
|
|
metavar='<replica-gigabytes>',
|
|
type=int,
|
|
default=None,
|
|
help=_(
|
|
"Capacity of share replicas in total. "
|
|
"Available only for microversion >= 2.53"
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--per-share-gigabytes',
|
|
metavar='<per-share-gigabytes>',
|
|
type=int,
|
|
default=None,
|
|
help=_(
|
|
'New value for the "per-share-gigabytes" quota. '
|
|
'Available only for microversion >= 2.62'
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--encryption-keys',
|
|
metavar='<encryption-keys>',
|
|
type=int,
|
|
default=None,
|
|
help=_(
|
|
'New value for the "encryption-keys" quota. '
|
|
'Available only for microversion >= 2.90'
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--force',
|
|
dest='force',
|
|
action="store_true",
|
|
default=None,
|
|
help=_('Force update the quota. Not applicable for class update.'),
|
|
)
|
|
return parser
|
|
|
|
def take_action(self, parsed_args):
|
|
share_client = self.app.client_manager.share
|
|
identity_client = self.app.client_manager.identity
|
|
|
|
user_id = None
|
|
if parsed_args.user:
|
|
user_id = utils.find_resource(
|
|
identity_client.users, parsed_args.user
|
|
).id
|
|
|
|
kwargs = {
|
|
"shares": parsed_args.shares,
|
|
"snapshots": parsed_args.snapshots,
|
|
"gigabytes": parsed_args.gigabytes,
|
|
"snapshot_gigabytes": parsed_args.snapshot_gigabytes,
|
|
"share_networks": parsed_args.share_networks,
|
|
}
|
|
|
|
if parsed_args.share_type is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.39'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'share type' quotas are available only starting with "
|
|
"'2.39' API microversion."
|
|
)
|
|
)
|
|
kwargs["share_type"] = parsed_args.share_type
|
|
if parsed_args.share_groups is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.40'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'share group' quotas are available only "
|
|
"starting with '2.40' API microversion."
|
|
)
|
|
)
|
|
kwargs["share_groups"] = parsed_args.share_groups
|
|
if parsed_args.share_group_snapshots is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.40'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'share group snapshots' quotas are available only "
|
|
"starting with '2.40' API microversion."
|
|
)
|
|
)
|
|
kwargs["share_group_snapshots"] = parsed_args.share_group_snapshots
|
|
if parsed_args.share_replicas is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.53'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"setting the number of 'share replicas' is available "
|
|
"only starting with API microversion '2.53'."
|
|
)
|
|
)
|
|
kwargs["share_replicas"] = parsed_args.share_replicas
|
|
if parsed_args.replica_gigabytes is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.53'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"setting the capacity of share replicas in total "
|
|
"is available only starting with API microversion "
|
|
"'2.53'."
|
|
)
|
|
)
|
|
kwargs["replica_gigabytes"] = parsed_args.replica_gigabytes
|
|
if parsed_args.per_share_gigabytes is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.62'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'per share gigabytes' quotas are available only "
|
|
"starting with '2.62' API microversion."
|
|
)
|
|
)
|
|
kwargs["per_share_gigabytes"] = parsed_args.per_share_gigabytes
|
|
if parsed_args.encryption_keys is not None:
|
|
if share_client.api_version < api_versions.APIVersion('2.90'):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'encryption keys' quotas are available only "
|
|
"starting with '2.90' API microversion."
|
|
)
|
|
)
|
|
kwargs["encryption_keys"] = parsed_args.encryption_keys
|
|
|
|
if all(value is None for value in kwargs.values()):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"Nothing to set. "
|
|
"New quota must be specified to at least one of the "
|
|
"following resources: 'shares', 'snapshots', 'gigabytes', "
|
|
"'snapshot-gigabytes', 'share-networks', 'share-type', "
|
|
"'share-groups', 'share-group-snapshots', "
|
|
"'share-replicas', 'replica-gigabytes', "
|
|
"'per-share-gigabytes', 'encryption_keys'"
|
|
)
|
|
)
|
|
|
|
if parsed_args.quota_class:
|
|
kwargs.update(
|
|
{
|
|
"class_name": parsed_args.project,
|
|
}
|
|
)
|
|
try:
|
|
share_client.quota_classes.update(**kwargs)
|
|
except Exception as e:
|
|
msg = _(
|
|
"Failed to set quotas for class '%(project)s': '%(e)s'"
|
|
)
|
|
raise exceptions.CommandError(
|
|
msg % {'project': parsed_args.project, 'e': e}
|
|
)
|
|
else:
|
|
project_id = utils.find_resource(
|
|
identity_client.projects, parsed_args.project
|
|
).id
|
|
|
|
kwargs.update(
|
|
{
|
|
"tenant_id": project_id,
|
|
"force": parsed_args.force,
|
|
"user_id": user_id,
|
|
}
|
|
)
|
|
|
|
try:
|
|
share_client.quotas.update(**kwargs)
|
|
except Exception as e:
|
|
msg = _(
|
|
"Failed to set quotas for project '%(project)s': '%(e)s'"
|
|
)
|
|
raise exceptions.CommandError(
|
|
msg % {'project': parsed_args.project, 'e': e}
|
|
)
|
|
|
|
|
|
class QuotaShow(command.ShowOne):
|
|
"""List the quotas for a project or project/user or project/share-type."""
|
|
|
|
_description = _("Show Quota")
|
|
|
|
def get_parser(self, prog_name):
|
|
parser = super().get_parser(prog_name)
|
|
quota_type = parser.add_mutually_exclusive_group()
|
|
parser.add_argument(
|
|
'project',
|
|
metavar='<project>',
|
|
help=_('Name or ID of the project to list quotas for.'),
|
|
)
|
|
quota_type.add_argument(
|
|
'--user',
|
|
metavar='<user>',
|
|
default=None,
|
|
help=_(
|
|
"Name or ID of user to list the quotas for. Optional. "
|
|
"Mutually exclusive with '--share-type'."
|
|
),
|
|
)
|
|
quota_type.add_argument(
|
|
'--share-type',
|
|
metavar='<share-type>',
|
|
type=str,
|
|
default=None,
|
|
help=_(
|
|
"Name or ID of a share type to list the quotas for. "
|
|
"Optional. "
|
|
"Mutually exclusive with '--user'. "
|
|
"Available only for microversion >= 2.39"
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--detail',
|
|
action='store_true',
|
|
default=False,
|
|
help=_(
|
|
'Optional flag to indicate whether to show quota in detail.'
|
|
' Default false, available only for microversion >= 2.25.'
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
'--defaults',
|
|
action='store_true',
|
|
default=False,
|
|
help=_('Show the default quotas for the project.'),
|
|
)
|
|
return parser
|
|
|
|
def take_action(self, parsed_args):
|
|
share_client = self.app.client_manager.share
|
|
identity_client = self.app.client_manager.identity
|
|
|
|
user_id = None
|
|
if parsed_args.user:
|
|
user_id = utils.find_resource(
|
|
identity_client.users, parsed_args.user
|
|
).id
|
|
|
|
project_id = utils.find_resource(
|
|
identity_client.projects, parsed_args.project
|
|
).id
|
|
|
|
quotas = {}
|
|
if parsed_args.defaults:
|
|
quotas = share_client.quotas.defaults(project_id)
|
|
else:
|
|
kwargs = {
|
|
"tenant_id": project_id,
|
|
"user_id": user_id,
|
|
"detail": parsed_args.detail,
|
|
}
|
|
if parsed_args.share_type is not None:
|
|
if share_client.api_version < api_versions.APIVersion("2.39"):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'share type' quotas are available only "
|
|
"starting with '2.39' API microversion."
|
|
)
|
|
)
|
|
kwargs["share_type"] = parsed_args.share_type
|
|
|
|
quotas = share_client.quotas.get(**kwargs)
|
|
|
|
printable_quotas = {}
|
|
for quota_k, quota_v in sorted(quotas.to_dict().items()):
|
|
if isinstance(quota_v, dict):
|
|
quota_v = '\n'.join(
|
|
[f'{k} = {v}' for k, v in sorted(quota_v.items())]
|
|
)
|
|
printable_quotas[quota_k] = quota_v
|
|
|
|
return self.dict2columns(printable_quotas)
|
|
|
|
|
|
class QuotaDelete(command.Command):
|
|
"""Delete quota for project/user or project/share-type.
|
|
|
|
The quota will revert back to default.
|
|
"""
|
|
|
|
_description = _("Delete Quota")
|
|
|
|
def get_parser(self, prog_name):
|
|
parser = super().get_parser(prog_name)
|
|
quota_type = parser.add_mutually_exclusive_group()
|
|
parser.add_argument(
|
|
'project',
|
|
metavar='<project>',
|
|
help=_('Name or ID of the project to delete quotas for.'),
|
|
)
|
|
quota_type.add_argument(
|
|
'--user',
|
|
metavar='<user>',
|
|
default=None,
|
|
help=_(
|
|
"Name or ID of user to delete the quotas for. Optional. "
|
|
"Mutually exclusive with '--share-type'."
|
|
),
|
|
)
|
|
quota_type.add_argument(
|
|
'--share-type',
|
|
metavar='<share-type>',
|
|
type=str,
|
|
default=None,
|
|
help=_(
|
|
"Name or ID of a share type to delete the quotas for. "
|
|
"Optional. "
|
|
"Mutually exclusive with '--user'. "
|
|
"Available only for microversion >= 2.39"
|
|
),
|
|
)
|
|
return parser
|
|
|
|
def take_action(self, parsed_args):
|
|
share_client = self.app.client_manager.share
|
|
identity_client = self.app.client_manager.identity
|
|
|
|
user_id = None
|
|
if parsed_args.user:
|
|
user_id = utils.find_resource(
|
|
identity_client.users, parsed_args.user
|
|
).id
|
|
|
|
project_id = utils.find_resource(
|
|
identity_client.projects, parsed_args.project
|
|
).id
|
|
|
|
kwargs = {"tenant_id": project_id, "user_id": user_id}
|
|
if parsed_args.share_type:
|
|
if share_client.api_version < api_versions.APIVersion("2.39"):
|
|
raise exceptions.CommandError(
|
|
_(
|
|
"'share type' quotas are available only starting with "
|
|
"API microversion '2.39'."
|
|
)
|
|
)
|
|
kwargs["share_type"] = parsed_args.share_type
|
|
|
|
share_client.quotas.delete(**kwargs)
|