Human readable export location CLI changes
OpenStack CLI option is added to support user friently export location. example command: $ openstack share create nfs 1 --name share_name --mount-point-name custom_export_path partially-implements: bp human-readable-export-locations Depends-On: I72ac7e24ddd4330d76cafd5e7f78bac2b0174883 Change-Id: If896065a74fc4ebabd09b677e5eb0329cecfaab9
This commit is contained in:
parent
5000f1cb1f
commit
b097cec84f
@ -27,7 +27,7 @@ from manilaclient import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
MAX_VERSION = '2.83'
|
||||
MAX_VERSION = '2.84'
|
||||
MIN_VERSION = '2.0'
|
||||
DEPRECATED_VERSION = '1.0'
|
||||
_VERSIONED_METHOD_MAP = {}
|
||||
|
@ -188,6 +188,13 @@ class CreateShare(command.ShowOne):
|
||||
"possible keys are same_host, different_host."
|
||||
"(repeat option to set multiple hints)"),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--mount-point-name',
|
||||
metavar="<mount_point_name>",
|
||||
default=None,
|
||||
help=_('Optional custom export location. Available for '
|
||||
'microversion >= 2.84')
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
@ -232,6 +239,15 @@ class CreateShare(command.ShowOne):
|
||||
snapshot_id = snapshot.id
|
||||
size = max(size or 0, snapshot.size)
|
||||
|
||||
mount_point_name = None
|
||||
if parsed_args.mount_point_name:
|
||||
if share_client.api_version < api_versions.APIVersion('2.84'):
|
||||
raise exceptions.CommandError(
|
||||
'Setting share mount point name is '
|
||||
'available only for API microversion >= 2.84')
|
||||
else:
|
||||
mount_point_name = parsed_args.mount_point_name
|
||||
|
||||
scheduler_hints = {}
|
||||
if parsed_args.scheduler_hint:
|
||||
if share_client.api_version < api_versions.APIVersion('2.65'):
|
||||
@ -271,7 +287,8 @@ class CreateShare(command.ShowOne):
|
||||
'is_public': parsed_args.public,
|
||||
'availability_zone': parsed_args.availability_zone,
|
||||
'share_group_id': share_group,
|
||||
'scheduler_hints': scheduler_hints
|
||||
'scheduler_hints': scheduler_hints,
|
||||
'mount_point_name': mount_point_name,
|
||||
}
|
||||
|
||||
share = share_client.shares.create(**body)
|
||||
|
@ -139,6 +139,7 @@ class FakeShare(object):
|
||||
"revert_to_snapshot_support": False,
|
||||
"source_share_group_snapshot_member_id": None,
|
||||
"scheduler_hints": {},
|
||||
"mount_point_name": None,
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
|
@ -132,7 +132,8 @@ class TestShareCreate(TestShare):
|
||||
share_type=self.share_type.id,
|
||||
size=self.new_share.size,
|
||||
snapshot_id=None,
|
||||
scheduler_hints={}
|
||||
scheduler_hints={},
|
||||
mount_point_name=None,
|
||||
)
|
||||
|
||||
self.assertCountEqual(self.columns, columns)
|
||||
@ -180,7 +181,8 @@ class TestShareCreate(TestShare):
|
||||
share_type=self.share_type.id,
|
||||
size=self.new_share.size,
|
||||
snapshot_id=None,
|
||||
scheduler_hints={}
|
||||
scheduler_hints={},
|
||||
mount_point_name=None,
|
||||
)
|
||||
|
||||
self.assertCountEqual(self.columns, columns)
|
||||
@ -227,6 +229,49 @@ class TestShareCreate(TestShare):
|
||||
snapshot_id=None,
|
||||
scheduler_hints={'same_host': shares[0].id,
|
||||
'different_host': shares[1].id},
|
||||
mount_point_name=None,
|
||||
)
|
||||
|
||||
self.assertCountEqual(self.columns, columns)
|
||||
self.assertCountEqual(self.datalist, data)
|
||||
|
||||
def test_share_create_mount_point_name(self):
|
||||
"""Verifies that the mount point name has been passed correctly."""
|
||||
self.app.client_manager.share.api_version = api_versions.APIVersion(
|
||||
"2.84")
|
||||
|
||||
mount_point_name = "fake_mp"
|
||||
|
||||
arglist = [
|
||||
self.new_share.share_proto,
|
||||
str(self.new_share.size),
|
||||
'--share-type', self.share_type.id,
|
||||
'--mount-point-name', mount_point_name,
|
||||
]
|
||||
verifylist = [
|
||||
('share_proto', self.new_share.share_proto),
|
||||
('size', self.new_share.size),
|
||||
('mount_point_name', mount_point_name),
|
||||
('share_type', self.share_type.id),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.shares_mock.create.assert_called_with(
|
||||
availability_zone=None,
|
||||
description=None,
|
||||
is_public=False,
|
||||
metadata={},
|
||||
name=None,
|
||||
share_group_id=None,
|
||||
share_network=None,
|
||||
share_proto=self.new_share.share_proto,
|
||||
share_type=self.share_type.id,
|
||||
size=self.new_share.size,
|
||||
snapshot_id=None,
|
||||
scheduler_hints={},
|
||||
mount_point_name='fake_mp',
|
||||
)
|
||||
|
||||
self.assertCountEqual(self.columns, columns)
|
||||
@ -269,7 +314,8 @@ class TestShareCreate(TestShare):
|
||||
share_type=None,
|
||||
size=self.new_share.size,
|
||||
snapshot_id=self.share_snapshot.id,
|
||||
scheduler_hints={}
|
||||
scheduler_hints={},
|
||||
mount_point_name=None,
|
||||
)
|
||||
self.assertCountEqual(self.columns, columns)
|
||||
self.assertCountEqual(self.datalist, data)
|
||||
@ -305,7 +351,8 @@ class TestShareCreate(TestShare):
|
||||
share_type=self.share_type.id,
|
||||
size=self.new_share.size,
|
||||
snapshot_id=None,
|
||||
scheduler_hints={}
|
||||
scheduler_hints={},
|
||||
mount_point_name=None,
|
||||
)
|
||||
|
||||
self.shares_mock.get.assert_called_with(self.new_share.id)
|
||||
@ -345,7 +392,8 @@ class TestShareCreate(TestShare):
|
||||
share_type=self.share_type.id,
|
||||
size=self.new_share.size,
|
||||
snapshot_id=None,
|
||||
scheduler_hints={}
|
||||
scheduler_hints={},
|
||||
mount_point_name=None,
|
||||
)
|
||||
|
||||
mock_logger.error.assert_called_with(
|
||||
|
@ -140,6 +140,29 @@ class SharesTest(utils.TestCase):
|
||||
availability_zone=availability_zone)
|
||||
cs.assert_called('POST', '/shares', body)
|
||||
|
||||
@ddt.data({'mount_point_name': 'fake_mount_pt1'},
|
||||
{'mount_point_name': 'fake_mount_pt2'})
|
||||
@ddt.unpack
|
||||
def test_create_share_with_mount_point_name(self, mount_point_name):
|
||||
body = {
|
||||
'share': {
|
||||
'is_public': False,
|
||||
'share_type': None,
|
||||
'name': None,
|
||||
'snapshot_id': None,
|
||||
'description': None,
|
||||
'metadata': {},
|
||||
'share_proto': 'nfs',
|
||||
'share_network_id': None,
|
||||
'size': 1,
|
||||
'availability_zone': None,
|
||||
'scheduler_hints': {},
|
||||
'mount_point_name': mount_point_name,
|
||||
}
|
||||
}
|
||||
cs.shares.create('nfs', 1, mount_point_name=mount_point_name)
|
||||
cs.assert_called('POST', '/shares', body)
|
||||
|
||||
@ddt.data(
|
||||
type('ShareUUID', (object, ), {'uuid': '1234'}),
|
||||
type('ShareID', (object, ), {'id': '1234'}),
|
||||
|
@ -124,7 +124,8 @@ class ShareManager(base.MetadataCapableManager):
|
||||
def create(self, share_proto, size, snapshot_id=None, name=None,
|
||||
description=None, metadata=None, share_network=None,
|
||||
share_type=None, is_public=False, availability_zone=None,
|
||||
share_group_id=None, scheduler_hints=None, return_raw=False):
|
||||
share_group_id=None, scheduler_hints=None, return_raw=False,
|
||||
mount_point_name=None):
|
||||
"""Create a share.
|
||||
|
||||
:param share_proto: text - share protocol for new share available
|
||||
@ -142,6 +143,9 @@ class ShareManager(base.MetadataCapableManager):
|
||||
:param scheduler_hints: dict - hints for the scheduler to place share
|
||||
on most appropriate host e.g. keys are same_host for affinity and
|
||||
different_host for anti-affinity
|
||||
:param mount_point_name: text - share human-readable mount point name.
|
||||
This name will be reflected in export location once
|
||||
share is created.
|
||||
:rtype: :class:`Share`
|
||||
"""
|
||||
share_metadata = metadata if metadata is not None else dict()
|
||||
@ -163,6 +167,9 @@ class ShareManager(base.MetadataCapableManager):
|
||||
if share_group_id:
|
||||
body['share_group_id'] = share_group_id
|
||||
|
||||
if mount_point_name:
|
||||
body['mount_point_name'] = mount_point_name
|
||||
|
||||
return self._create('/shares', {'share': body}, 'share',
|
||||
return_raw=return_raw)
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
---
|
||||
features:
|
||||
- In the 2.84 API version, a new option, ``mount_point_name``, has been
|
||||
introduced to the share creation command. This option allow users
|
||||
to specify a more intuitive ``mount_point_name`` that will be reflected
|
||||
in the share's export location. However, for this feature to be available
|
||||
to users, administrators must first enable an extra-spec in the
|
||||
share type. In addition, administrators need to set an extra-spec named
|
||||
``provisioning:mount_point_prefix``. The Manila service will combine
|
||||
this prefix with the mount point name that user provides during share
|
||||
creation. If the ``provisioning:mount_point_prefix`` is not set for
|
||||
a share type, but ``mount_point_name_support`` is enabled, the share's
|
||||
export location will default to using the project_id as a prefix.
|
||||
Please note that shares created with a project_id prefix cannot be
|
||||
transferred. To move these shares to a different project,
|
||||
an admin must manually unmount them from the current project and mount
|
||||
them to the target project. A new capability, ``mount_point_name_support``,
|
||||
allows the driver to inform the scheduler about its support for the
|
||||
mount_point_name feature.
|
Loading…
Reference in New Issue
Block a user