Metadata for share export location
Adds set and unset commands for export location properties within unified CLI Depends-On: Icf096a5cbc650f02eca68d714c876eb854499b9b Partially-implements: bp metadata-for-share-resources Change-Id: I3878868c2359fba7aa8a49421a31a952a5776766
This commit is contained in:
parent
0e74a7bcf2
commit
5ba65e94e4
@ -27,7 +27,7 @@ from manilaclient import utils
|
|||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
MAX_VERSION = '2.84'
|
MAX_VERSION = '2.87'
|
||||||
MIN_VERSION = '2.0'
|
MIN_VERSION = '2.0'
|
||||||
DEPRECATED_VERSION = '1.0'
|
DEPRECATED_VERSION = '1.0'
|
||||||
_VERSIONED_METHOD_MAP = {}
|
_VERSIONED_METHOD_MAP = {}
|
||||||
|
@ -1179,8 +1179,15 @@ class ShareExportLocationShow(command.ShowOne):
|
|||||||
share=share,
|
share=share,
|
||||||
export_location=parsed_args.export_location
|
export_location=parsed_args.export_location
|
||||||
)
|
)
|
||||||
|
data = export_location._info
|
||||||
|
data.update(
|
||||||
|
{
|
||||||
|
'properties':
|
||||||
|
format_columns.DictColumn(data.pop('metadata', {})),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return self.dict2columns(export_location._info)
|
return self.dict2columns(data)
|
||||||
|
|
||||||
|
|
||||||
class ShareExportLocationList(command.Lister):
|
class ShareExportLocationList(command.Lister):
|
||||||
@ -1218,6 +1225,120 @@ class ShareExportLocationList(command.Lister):
|
|||||||
(s, list_of_keys) for s in export_locations))
|
(s, list_of_keys) for s in export_locations))
|
||||||
|
|
||||||
|
|
||||||
|
class ShareExportLocationSet(command.Command):
|
||||||
|
"""Set an export location property."""
|
||||||
|
|
||||||
|
_description = _("Set an export location property.")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShareExportLocationSet, self).get_parser(
|
||||||
|
prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'share',
|
||||||
|
metavar="<share>",
|
||||||
|
help=_('Name or ID of share')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'export_location',
|
||||||
|
metavar="<export_location>",
|
||||||
|
help=_('ID of the export location')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--property",
|
||||||
|
metavar="<key=value>",
|
||||||
|
default={},
|
||||||
|
action=parseractions.KeyValueAction,
|
||||||
|
help=_("Set a property to this export location "
|
||||||
|
"(repeat option to set multiple properties). "
|
||||||
|
"Available only for microversion >= 2.87."),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
share_client = self.app.client_manager.share
|
||||||
|
share_id = apiutils.find_resource(
|
||||||
|
share_client.shares,
|
||||||
|
parsed_args.share).id
|
||||||
|
|
||||||
|
if (parsed_args.property and
|
||||||
|
share_client.api_version < api_versions.APIVersion("2.87")):
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
"Property can be specified only with manila API "
|
||||||
|
"version >= 2.87.")
|
||||||
|
|
||||||
|
if parsed_args.property:
|
||||||
|
try:
|
||||||
|
share_client.share_export_locations.set_metadata(
|
||||||
|
share_id,
|
||||||
|
parsed_args.property,
|
||||||
|
subresource=parsed_args.export_location)
|
||||||
|
except Exception as e:
|
||||||
|
raise exceptions.CommandError(_(
|
||||||
|
"Failed to set export location property "
|
||||||
|
"'%(properties)s': %(e)s") %
|
||||||
|
{'properties': parsed_args.property, 'e': e}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ShareExportLocationUnset(command.Command):
|
||||||
|
"""Unset a share export location property"""
|
||||||
|
_description = _("Unset a share export location property")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShareExportLocationUnset, self).get_parser(
|
||||||
|
prog_name)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'share',
|
||||||
|
metavar="<share>",
|
||||||
|
help=_('Name or ID of share')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'export_location',
|
||||||
|
metavar="<export_location>",
|
||||||
|
help=_('ID of the export location')
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--property",
|
||||||
|
metavar="<key>",
|
||||||
|
action='append',
|
||||||
|
help=_("Remove a property from export location "
|
||||||
|
"(repeat option to remove multiple properties). "
|
||||||
|
"Available only for microversion >= 2.87."),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
share_client = self.app.client_manager.share
|
||||||
|
share_id = apiutils.find_resource(
|
||||||
|
share_client.shares,
|
||||||
|
parsed_args.share).id
|
||||||
|
|
||||||
|
if (parsed_args.property and
|
||||||
|
share_client.api_version < api_versions.APIVersion("2.87")):
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
"Property can be specified only with manila API "
|
||||||
|
"version >= 2.87.")
|
||||||
|
|
||||||
|
if parsed_args.property:
|
||||||
|
result = 0
|
||||||
|
for key in parsed_args.property:
|
||||||
|
try:
|
||||||
|
share_client.share_export_locations.delete_metadata(
|
||||||
|
share_id, [key],
|
||||||
|
subresource=parsed_args.export_location)
|
||||||
|
except Exception as e:
|
||||||
|
result += 1
|
||||||
|
LOG.error("Failed to unset export location property "
|
||||||
|
"'%(key)s': %(e)s", {'key': key, 'e': e})
|
||||||
|
if result > 0:
|
||||||
|
total = len(parsed_args.property)
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
f"{result} of {total} export location properties failed "
|
||||||
|
f"to be unset.")
|
||||||
|
|
||||||
|
|
||||||
class ShowShareProperties(command.ShowOne):
|
class ShowShareProperties(command.ShowOne):
|
||||||
"""Show properties of a share"""
|
"""Show properties of a share"""
|
||||||
_description = _("Show share properties")
|
_description = _("Show share properties")
|
||||||
|
@ -330,6 +330,7 @@ class FakeShareExportLocation(object):
|
|||||||
"id": "id-" + uuid.uuid4().hex,
|
"id": "id-" + uuid.uuid4().hex,
|
||||||
"is_admin_only": False,
|
"is_admin_only": False,
|
||||||
"preferred": False,
|
"preferred": False,
|
||||||
|
"properties": {},
|
||||||
"updated_at": 'time-' + uuid.uuid4().hex,
|
"updated_at": 'time-' + uuid.uuid4().hex,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1910,6 +1910,148 @@ class TestShareExportLocationList(TestShare):
|
|||||||
self.assertCountEqual(self.values, data)
|
self.assertCountEqual(self.values, data)
|
||||||
|
|
||||||
|
|
||||||
|
class TestExportLocationSet(TestShare):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestExportLocationSet, self).setUp()
|
||||||
|
|
||||||
|
self._share = manila_fakes.FakeShare.create_one_share(
|
||||||
|
methods={"set_metadata": None}
|
||||||
|
)
|
||||||
|
self.shares_mock.get.return_value = self._share
|
||||||
|
|
||||||
|
self._export_location = (
|
||||||
|
manila_fakes.FakeShareExportLocation.create_one_export_location(
|
||||||
|
{'fake_share_instance_id': self._share.id}))
|
||||||
|
|
||||||
|
self.export_locations_mock.get.return_value = (
|
||||||
|
self._export_location
|
||||||
|
)
|
||||||
|
|
||||||
|
self.cmd = osc_shares.ShareExportLocationSet(self.app, None)
|
||||||
|
|
||||||
|
def test_share_set_export_location_property(self):
|
||||||
|
self.app.client_manager.share.api_version = api_versions.APIVersion(
|
||||||
|
'2.87'
|
||||||
|
)
|
||||||
|
arglist = [
|
||||||
|
self._share.id,
|
||||||
|
self._export_location.id,
|
||||||
|
'--property', 'Bobcat=manila',
|
||||||
|
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('share', self._share.id),
|
||||||
|
('export_location', self._export_location.id),
|
||||||
|
('property', {'Bobcat': 'manila'}),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
self.export_locations_mock.set_metadata.assert_called_once_with(
|
||||||
|
self._share.id, {'Bobcat': 'manila'},
|
||||||
|
subresource=self._export_location.id)
|
||||||
|
|
||||||
|
def test_share_set_export_location_property_exception(self):
|
||||||
|
self.app.client_manager.share.api_version = api_versions.APIVersion(
|
||||||
|
'2.87'
|
||||||
|
)
|
||||||
|
arglist = [
|
||||||
|
self._share.id,
|
||||||
|
self._export_location.id,
|
||||||
|
'--property', 'key=',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('share', self._share.id),
|
||||||
|
('export_location', self._export_location.id),
|
||||||
|
('property', {'key': ''}),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.export_locations_mock.set_metadata.assert_called_once_with(
|
||||||
|
self._share.id, {'key': ''},
|
||||||
|
subresource=self._export_location.id)
|
||||||
|
|
||||||
|
self.export_locations_mock.set_metadata.side_effect = (
|
||||||
|
exceptions.BadRequest)
|
||||||
|
self.assertRaises(
|
||||||
|
osc_exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
|
class TestExportLocationUnset(TestShare):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestExportLocationUnset, self).setUp()
|
||||||
|
|
||||||
|
self._share = manila_fakes.FakeShare.create_one_share(
|
||||||
|
methods={"set_metadata": None}
|
||||||
|
)
|
||||||
|
self.shares_mock.get.return_value = self._share
|
||||||
|
|
||||||
|
self._export_location = (
|
||||||
|
manila_fakes.FakeShareExportLocation.create_one_export_location(
|
||||||
|
{'fake_share_instance_id': self._share.id}))
|
||||||
|
|
||||||
|
self.export_locations_mock.get.return_value = (
|
||||||
|
self._export_location
|
||||||
|
)
|
||||||
|
|
||||||
|
self.cmd = osc_shares.ShareExportLocationUnset(self.app, None)
|
||||||
|
|
||||||
|
def test_share_unset_export_location_property(self):
|
||||||
|
self.app.client_manager.share.api_version = api_versions.APIVersion(
|
||||||
|
'2.87'
|
||||||
|
)
|
||||||
|
arglist = [
|
||||||
|
self._share.id,
|
||||||
|
self._export_location.id,
|
||||||
|
'--property', 'Bobcat',
|
||||||
|
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('share', self._share.id),
|
||||||
|
('export_location', self._export_location.id),
|
||||||
|
('property', ['Bobcat']),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
self.export_locations_mock.delete_metadata.assert_called_once_with(
|
||||||
|
self._share.id, ['Bobcat'],
|
||||||
|
subresource=self._export_location.id)
|
||||||
|
|
||||||
|
def test_share_unset_export_location_property_exception(self):
|
||||||
|
self.app.client_manager.share.api_version = api_versions.APIVersion(
|
||||||
|
'2.87'
|
||||||
|
)
|
||||||
|
arglist = [
|
||||||
|
self._share.id,
|
||||||
|
self._export_location.id,
|
||||||
|
'--property', 'key',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('share', self._share.id),
|
||||||
|
('export_location', self._export_location.id),
|
||||||
|
('property', ['key']),
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.export_locations_mock.delete_metadata.assert_has_calls([
|
||||||
|
mock.call(self._share.id, ['key'],
|
||||||
|
subresource=self._export_location.id)])
|
||||||
|
|
||||||
|
self.export_locations_mock.delete_metadata.side_effect = (
|
||||||
|
exceptions.NotFound)
|
||||||
|
self.assertRaises(
|
||||||
|
osc_exceptions.CommandError, self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
class TestShowShareProperties(TestShare):
|
class TestShowShareProperties(TestShare):
|
||||||
|
|
||||||
properties = {
|
properties = {
|
||||||
|
@ -27,9 +27,11 @@ class ShareExportLocation(base.Resource):
|
|||||||
return self._info[key]
|
return self._info[key]
|
||||||
|
|
||||||
|
|
||||||
class ShareExportLocationManager(base.ManagerWithFind):
|
class ShareExportLocationManager(base.MetadataCapableManager):
|
||||||
"""Manage :class:`ShareExportLocation` resources."""
|
"""Manage :class:`ShareExportLocation` resources."""
|
||||||
resource_class = ShareExportLocation
|
resource_class = ShareExportLocation
|
||||||
|
resource_path = '/shares'
|
||||||
|
subresource_path = '/export_locations'
|
||||||
|
|
||||||
@api_versions.wraps("2.9")
|
@api_versions.wraps("2.9")
|
||||||
def list(self, share, search_opts=None):
|
def list(self, share, search_opts=None):
|
||||||
@ -47,3 +49,23 @@ class ShareExportLocationManager(base.ManagerWithFind):
|
|||||||
"/shares/%(share_id)s/export_locations/%(export_location_id)s" % {
|
"/shares/%(share_id)s/export_locations/%(export_location_id)s" % {
|
||||||
"share_id": share_id,
|
"share_id": share_id,
|
||||||
"export_location_id": export_location_id}, "export_location")
|
"export_location_id": export_location_id}, "export_location")
|
||||||
|
|
||||||
|
@api_versions.wraps('2.87')
|
||||||
|
def get_metadata(self, share, share_export_location):
|
||||||
|
return super(ShareExportLocationManager, self).get_metadata(
|
||||||
|
share, subresource=share_export_location)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.87')
|
||||||
|
def set_metadata(self, resource, metadata, subresource=None):
|
||||||
|
return super(ShareExportLocationManager, self).set_metadata(
|
||||||
|
resource, metadata, subresource=subresource)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.87')
|
||||||
|
def delete_metadata(self, resource, keys, subresource=None):
|
||||||
|
return super(ShareExportLocationManager, self).delete_metadata(
|
||||||
|
resource, keys, subresource=subresource)
|
||||||
|
|
||||||
|
@api_versions.wraps('2.87')
|
||||||
|
def update_all_metadata(self, resource, metadata, subresource=None):
|
||||||
|
return super(ShareExportLocationManager, self).update_all_metadata(
|
||||||
|
resource, metadata, subresource=subresource)
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds support to set and unset share export location properties
|
||||||
|
(only with the OpenStackClient).
|
@ -52,6 +52,8 @@ openstack.share.v2 =
|
|||||||
share_migration_show = manilaclient.osc.v2.share:ShareMigrationShow
|
share_migration_show = manilaclient.osc.v2.share:ShareMigrationShow
|
||||||
share_export_location_show = manilaclient.osc.v2.share:ShareExportLocationShow
|
share_export_location_show = manilaclient.osc.v2.share:ShareExportLocationShow
|
||||||
share_export_location_list = manilaclient.osc.v2.share:ShareExportLocationList
|
share_export_location_list = manilaclient.osc.v2.share:ShareExportLocationList
|
||||||
|
share_export_location_set = manilaclient.osc.v2.share:ShareExportLocationSet
|
||||||
|
share_export_location_unset = manilaclient.osc.v2.share:ShareExportLocationUnset
|
||||||
share_properties_show = manilaclient.osc.v2.share:ShowShareProperties
|
share_properties_show = manilaclient.osc.v2.share:ShowShareProperties
|
||||||
share_restore = manilaclient.osc.v2.share:RestoreShare
|
share_restore = manilaclient.osc.v2.share:RestoreShare
|
||||||
share_revert = manilaclient.osc.v2.share:RevertShare
|
share_revert = manilaclient.osc.v2.share:RevertShare
|
||||||
|
Loading…
Reference in New Issue
Block a user