python-manilaclient/manilaclient/osc/v2/share_types.py

451 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.
import logging
import six
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils as oscutils
from oslo_utils import strutils
from manilaclient import api_versions
from manilaclient.common._i18n import _
from manilaclient.common.apiclient import utils as apiutils
from manilaclient.common import constants
from manilaclient.osc import utils
LOG = logging.getLogger(__name__)
ATTRIBUTES = [
'id',
'name',
'visibility',
'is_default',
'required_extra_specs',
'optional_extra_specs',
'description'
]
def format_share_type(share_type):
# share_type_access:is_public (true/false) --> visibility (public/private)
is_public = 'share_type_access:is_public'
visibility = 'public' if share_type._info.get(is_public) else 'private'
share_type._info.pop(is_public, None)
# optional_extra_specs --> extra_specs without required_extra_specs
# required_extra_specs are displayed separately
optional_extra_specs = share_type.extra_specs
for key in share_type.required_extra_specs.keys():
optional_extra_specs.pop(key, None)
share_type._info.update(
{
'visibility': visibility,
'required_extra_specs': utils.format_properties(
share_type.required_extra_specs),
'optional_extra_specs': utils.format_properties(
optional_extra_specs),
}
)
return share_type
class CreateShareType(command.ShowOne):
"""Create new share type."""
_description = _(
"Create new share type")
log = logging.getLogger(__name__ + ".CreateShareType")
def get_parser(self, prog_name):
parser = super(CreateShareType, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar="<name>",
default=None,
help=_('Share type name')
)
parser.add_argument(
'spec_driver_handles_share_servers',
metavar="<spec_driver_handles_share_servers>",
default=None,
help=_("Required extra specification. "
"Valid values are 'true' and 'false'")
)
parser.add_argument(
"--description",
metavar="<description>",
default=None,
help=_("Share type description. "
"Available only for microversion >= 2.41."),
)
parser.add_argument(
"--snapshot-support",
metavar="<snapshot_support>",
default=None,
help=_("Boolean extra spec used for filtering of back ends "
"by their capability to create share snapshots."),
)
parser.add_argument(
"--create-share-from-snapshot-support",
metavar="<create_share_from_snapshot_support>",
default=None,
help=_("Boolean extra spec used for filtering of back ends "
"by their capability to create shares from snapshots."),
)
parser.add_argument(
"--revert-to-snapshot-support",
metavar="<revert_to_snapshot_support>",
default=False,
help=_("Boolean extra spec used for filtering of back ends "
"by their capability to revert shares to snapshots. "
"(Default is False)."),
)
parser.add_argument(
"--mount-snapshot-support",
metavar="<mount_snapshot_support>",
default=False,
help=_("Boolean extra spec used for filtering of back ends "
"by their capability to mount share snapshots. "
"(Default is False)."),
)
parser.add_argument(
"--extra-specs",
type=str,
nargs='*',
metavar='<key=value>',
default=None,
help=_("Extra specs key and value of share type that will be"
" used for share type creation. OPTIONAL: Default=None."
" example --extra-specs thin_provisioning='<is> True', "
"replication_type=readable."),
)
parser.add_argument(
'--public',
metavar="<public>",
default=True,
help=_('Make type accessible to the public (default true).')
)
return parser
def take_action(self, parsed_args):
share_client = self.app.client_manager.share
kwargs = {
'name': parsed_args.name
}
try:
kwargs['spec_driver_handles_share_servers'] = (
strutils.bool_from_string(
parsed_args.spec_driver_handles_share_servers,
strict=True))
except ValueError as e:
msg = ("Argument spec_driver_handles_share_servers "
"argument is not valid: %s" % six.text_type(e))
raise exceptions.CommandError(msg)
if parsed_args.description:
if share_client.api_version.matches(
api_versions.APIVersion("2.41"),
api_versions.APIVersion()):
kwargs['description'] = parsed_args.description
else:
raise exceptions.CommandError(
"Adding description to share type "
"is only available with API microversion >= 2.41")
if parsed_args.public:
kwargs['is_public'] = strutils.bool_from_string(
parsed_args.public, default=True)
extra_specs = {}
if parsed_args.extra_specs:
for item in parsed_args.extra_specs:
(key, value) = item.split('=', 1)
if key == 'driver_handles_share_servers':
msg = ("'driver_handles_share_servers' "
"is already set via positional argument.")
raise exceptions.CommandError(msg)
else:
extra_specs = utils.extract_extra_specs(
extra_specs, [item])
for key in constants.BOOL_SPECS:
value = getattr(parsed_args, key)
if value:
extra_specs = utils.extract_extra_specs(
extra_specs, [key + '=' + value])
kwargs['extra_specs'] = extra_specs
share_type = share_client.share_types.create(**kwargs)
formatted_type = format_share_type(share_type)
return (ATTRIBUTES, oscutils.get_dict_properties(
formatted_type._info, ATTRIBUTES))
class DeleteShareType(command.Command):
"""Delete a share type."""
_description = _("Delete a share type")
log = logging.getLogger(__name__ + ".DeleteShareType")
def get_parser(self, prog_name):
parser = super(DeleteShareType, self).get_parser(prog_name)
parser.add_argument(
'share_types',
metavar="<share_types>",
nargs="+",
help=_("Name or ID of the share type(s) to delete")
)
return parser
def take_action(self, parsed_args):
share_client = self.app.client_manager.share
result = 0
for share_type in parsed_args.share_types:
try:
share_type_obj = apiutils.find_resource(
share_client.share_types,
share_type)
share_client.share_types.delete(share_type_obj)
except Exception as e:
result += 1
LOG.error(_(
"Failed to delete share type with "
"name or ID '%(share_type)s': %(e)s"),
{'share_type': share_type, 'e': e})
if result > 0:
total = len(parsed_args.share_types)
msg = (_("%(result)s of %(total)s share types failed "
"to delete.") % {'result': result, 'total': total})
raise exceptions.CommandError(msg)
class SetShareType(command.Command):
"""Set share type properties."""
_description = _("Set share type properties")
log = logging.getLogger(__name__ + ".SetShareType")
def get_parser(self, prog_name):
parser = super(SetShareType, self).get_parser(prog_name)
parser.add_argument(
'share_type',
metavar="<share_type>",
help=_("Name or ID of the share type to modify")
)
parser.add_argument(
"--extra-specs",
type=str,
nargs='*',
metavar='<key=value>',
default=None,
help=_("Extra specs key and value of share type that will be"
" used for share type creation. OPTIONAL: Default=None."
" example --extra-specs thin_provisioning='<is> True', "
"replication_type=readable."),
)
parser.add_argument(
'--public',
metavar="<public>",
default=None,
help=_('New visibility of the share type. If set to True, '
'share type will be available to all projects '
'in the cloud. '
'Available only for microversion >= 2.50')
)
parser.add_argument(
"--description",
metavar="<description>",
default=None,
help=_("New description of share type. "
"Available only for microversion >= 2.50"),
)
parser.add_argument(
'--name',
metavar="<name>",
default=None,
help=_('New name of share type. '
'Available only for microversion >= 2.50')
)
return parser
def take_action(self, parsed_args):
share_client = self.app.client_manager.share
share_type = apiutils.find_resource(
share_client.share_types, parsed_args.share_type)
can_update = (
share_client.api_version >= api_versions.APIVersion('2.50'))
kwargs = {}
if parsed_args.name is not None:
if can_update:
kwargs['name'] = parsed_args.name
else:
raise exceptions.CommandError(
"Setting (new) name to share type "
"is only available with API microversion >= 2.50")
if parsed_args.description is not None:
if can_update:
kwargs['description'] = parsed_args.description
else:
raise exceptions.CommandError(
"Setting (new) description to share type "
"is only available with API microversion >= 2.50")
if parsed_args.public is not None:
if can_update:
kwargs['is_public'] = strutils.bool_from_string(
parsed_args.public, default=True)
else:
raise exceptions.CommandError(
"Setting visibility to share type "
"is only available with API microversion >= 2.50")
if kwargs:
share_type.update(**kwargs)
if parsed_args.extra_specs:
extra_specs = utils.extract_extra_specs(
extra_specs={},
specs_to_add=parsed_args.extra_specs)
try:
share_type.set_keys(extra_specs)
except Exception as e:
raise exceptions.CommandError(
"Failed to set share type key: %s" % e)
class UnsetShareType(command.Command):
"""Unset share type extra specs."""
_description = _("Unset share type extra specs")
log = logging.getLogger(__name__ + ".UnsetShareType")
def get_parser(self, prog_name):
parser = super(UnsetShareType, self).get_parser(prog_name)
parser.add_argument(
'share_type',
metavar="<share_type>",
help=_("Name or ID of the share type to modify")
)
parser.add_argument(
'extra_specs',
metavar='<key>',
nargs='+',
help=_('Remove extra_specs from this share type'),
)
return parser
def take_action(self, parsed_args):
share_client = self.app.client_manager.share
share_type = apiutils.find_resource(
share_client.share_types, parsed_args.share_type)
if parsed_args.extra_specs:
try:
share_type.unset_keys(parsed_args.extra_specs)
except Exception as e:
raise exceptions.CommandError(
"Failed to remove share type extra spec: %s" % e)
class ListShareType(command.Lister):
"""List Share Types."""
_description = _("List share types")
log = logging.getLogger(__name__ + ".ListShareType")
def get_parser(self, prog_name):
parser = super(ListShareType, self).get_parser(prog_name)
parser.add_argument(
'--all',
action='store_true',
default=False,
help=_('Display all share types whatever public or private. '
'Default=False. (Admin only)'),
)
parser.add_argument(
'--extra-specs',
type=str,
nargs='*',
metavar='<key=value>',
default=None,
help=_('Filter share types with extra specs (key=value). '
'Available only for API microversion >= 2.43. '
'OPTIONAL: Default=None.'),
)
return parser
def take_action(self, parsed_args):
share_client = self.app.client_manager.share
search_opts = {}
if parsed_args.extra_specs:
if share_client.api_version < api_versions.APIVersion("2.43"):
raise exceptions.CommandError(
"Filtering by 'extra_specs' is available only with "
"API microversion '2.43' and above.")
search_opts = {
'extra_specs': utils.extract_extra_specs(
extra_specs={},
specs_to_add=parsed_args.extra_specs)
}
share_types = share_client.share_types.list(
search_opts=search_opts,
show_all=parsed_args.all)
formatted_types = []
for share_type in share_types:
formatted_types.append(format_share_type(share_type))
values = (oscutils.get_dict_properties(
s._info, ATTRIBUTES) for s in formatted_types)
return (ATTRIBUTES, values)
class ShowShareType(command.ShowOne):
"""Show a share type."""
_description = _("Display share type details")
def get_parser(self, prog_name):
parser = super(ShowShareType, self).get_parser(prog_name)
parser.add_argument(
'share_type',
metavar="<share_type>",
help=_("Share type to display (name or ID)")
)
return parser
def take_action(self, parsed_args):
share_client = self.app.client_manager.share
share_type = apiutils.find_resource(
share_client.share_types,
parsed_args.share_type)
formatted_type = format_share_type(share_type)
return (ATTRIBUTES, oscutils.get_dict_properties(
formatted_type._info, ATTRIBUTES))