Merge "volume: Add 'block storage resource filter list' command"
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
=============================
|
||||||
|
block storage resource filter
|
||||||
|
=============================
|
||||||
|
|
||||||
|
Block Storage v3
|
||||||
|
|
||||||
|
.. autoprogram-cliff:: openstack.volume.v3
|
||||||
|
:command: block storage resource filter *
|
||||||
@@ -77,6 +77,7 @@ referring to both Compute and Volume quotas.
|
|||||||
* ``aggregate``: (**Compute**) a grouping of compute hosts
|
* ``aggregate``: (**Compute**) a grouping of compute hosts
|
||||||
* ``availability zone``: (**Compute**, **Network**, **Volume**) a logical partition of hosts or block storage or network services
|
* ``availability zone``: (**Compute**, **Network**, **Volume**) a logical partition of hosts or block storage or network services
|
||||||
* ``block storage cluster``: (**Volume**) clusters of volume services
|
* ``block storage cluster``: (**Volume**) clusters of volume services
|
||||||
|
* ``block storage resource filter``: (**Volume**) filters for volume service resources
|
||||||
* ``catalog``: (**Identity**) service catalog
|
* ``catalog``: (**Identity**) service catalog
|
||||||
* ``command``: (**Internal**) installed commands in the OSC process
|
* ``command``: (**Internal**) installed commands in the OSC process
|
||||||
* ``compute agent``: (**Compute**) a cloud Compute agent available to a hypervisor
|
* ``compute agent``: (**Compute**) a cloud Compute agent available to a hypervisor
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ group-update,volume group set,Updates a group. (Supported by API versions 3.13 -
|
|||||||
image-metadata,volume set --image-property,Sets or deletes volume image metadata.
|
image-metadata,volume set --image-property,Sets or deletes volume image metadata.
|
||||||
image-metadata-show,volume show,Shows volume image metadata.
|
image-metadata-show,volume show,Shows volume image metadata.
|
||||||
list,volume list,Lists all volumes.
|
list,volume list,Lists all volumes.
|
||||||
list-filters,,List enabled filters. (Supported by API versions 3.33 - 3.latest)
|
list-filters,block storage resource filter list,List enabled filters. (Supported by API versions 3.33 - 3.latest)
|
||||||
manage,volume create --remote-source k=v,Manage an existing volume.
|
manage,volume create --remote-source k=v,Manage an existing volume.
|
||||||
manageable-list,,Lists all manageable volumes. (Supported by API versions 3.8 - 3.latest)
|
manageable-list,,Lists all manageable volumes. (Supported by API versions 3.8 - 3.latest)
|
||||||
message-delete,volume message delete,Removes one or more messages. (Supported by API versions 3.3 - 3.latest)
|
message-delete,volume message delete,Removes one or more messages. (Supported by API versions 3.3 - 3.latest)
|
||||||
|
|||||||
|
@@ -42,6 +42,8 @@ class FakeVolumeClient(object):
|
|||||||
self.group_types.resource_class = fakes.FakeResource(None, {})
|
self.group_types.resource_class = fakes.FakeResource(None, {})
|
||||||
self.messages = mock.Mock()
|
self.messages = mock.Mock()
|
||||||
self.messages.resource_class = fakes.FakeResource(None, {})
|
self.messages.resource_class = fakes.FakeResource(None, {})
|
||||||
|
self.resource_filters = mock.Mock()
|
||||||
|
self.resource_filters.resource_class = fakes.FakeResource(None, {})
|
||||||
self.volumes = mock.Mock()
|
self.volumes = mock.Mock()
|
||||||
self.volumes.resource_class = fakes.FakeResource(None, {})
|
self.volumes.resource_class = fakes.FakeResource(None, {})
|
||||||
self.volume_types = mock.Mock()
|
self.volume_types = mock.Mock()
|
||||||
@@ -124,6 +126,53 @@ class FakeCluster:
|
|||||||
return clusters
|
return clusters
|
||||||
|
|
||||||
|
|
||||||
|
class FakeResourceFilter:
|
||||||
|
"""Fake one or more resource filters."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_one_resource_filter(attrs=None):
|
||||||
|
"""Create a fake resource filter.
|
||||||
|
|
||||||
|
:param attrs: A dictionary with all attributes of resource filter
|
||||||
|
:return: A FakeResource object with id, name, status, etc.
|
||||||
|
"""
|
||||||
|
attrs = attrs or {}
|
||||||
|
|
||||||
|
# Set default attribute
|
||||||
|
|
||||||
|
resource_filter_info = {
|
||||||
|
'filters': [
|
||||||
|
'name',
|
||||||
|
'status',
|
||||||
|
'image_metadata',
|
||||||
|
'bootable',
|
||||||
|
'migration_status',
|
||||||
|
],
|
||||||
|
'resource': 'volume',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Overwrite default attributes if there are some attributes set
|
||||||
|
resource_filter_info.update(attrs)
|
||||||
|
|
||||||
|
return fakes.FakeResource(None, resource_filter_info, loaded=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_resource_filters(attrs=None, count=2):
|
||||||
|
"""Create multiple fake resource filters.
|
||||||
|
|
||||||
|
:param attrs: A dictionary with all attributes of resource filter
|
||||||
|
:param count: The number of resource filters to be faked
|
||||||
|
:return: A list of FakeResource objects
|
||||||
|
"""
|
||||||
|
resource_filters = []
|
||||||
|
for n in range(0, count):
|
||||||
|
resource_filters.append(
|
||||||
|
FakeResourceFilter.create_one_resource_filter(attrs)
|
||||||
|
)
|
||||||
|
|
||||||
|
return resource_filters
|
||||||
|
|
||||||
|
|
||||||
class FakeVolumeGroup:
|
class FakeVolumeGroup:
|
||||||
"""Fake one or more volume groups."""
|
"""Fake one or more volume groups."""
|
||||||
|
|
||||||
@@ -309,11 +358,10 @@ class FakeVolumeMessage:
|
|||||||
# Overwrite default attributes if there are some attributes set
|
# Overwrite default attributes if there are some attributes set
|
||||||
message_info.update(attrs)
|
message_info.update(attrs)
|
||||||
|
|
||||||
message = fakes.FakeResource(
|
return fakes.FakeResource(
|
||||||
None,
|
None,
|
||||||
message_info,
|
message_info,
|
||||||
loaded=True)
|
loaded=True)
|
||||||
return message
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_volume_messages(attrs=None, count=2):
|
def create_volume_messages(attrs=None, count=2):
|
||||||
@@ -402,11 +450,10 @@ class FakeVolumeAttachment:
|
|||||||
# Overwrite default attributes if there are some attributes set
|
# Overwrite default attributes if there are some attributes set
|
||||||
attachment_info.update(attrs)
|
attachment_info.update(attrs)
|
||||||
|
|
||||||
attachment = fakes.FakeResource(
|
return fakes.FakeResource(
|
||||||
None,
|
None,
|
||||||
attachment_info,
|
attachment_info,
|
||||||
loaded=True)
|
loaded=True)
|
||||||
return attachment
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_volume_attachments(attrs=None, count=2):
|
def create_volume_attachments(attrs=None, count=2):
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
# 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 cinderclient import api_versions
|
||||||
|
from osc_lib import exceptions
|
||||||
|
|
||||||
|
from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
|
||||||
|
from openstackclient.volume.v3 import block_storage_resource_filter
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlockStorageResourceFilter(volume_fakes.TestVolume):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
# Get a shortcut to the ResourceFilterManager Mock
|
||||||
|
self.resource_filter_mock = \
|
||||||
|
self.app.client_manager.volume.resource_filters
|
||||||
|
self.resource_filter_mock.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlockStorageResourceFilterList(TestBlockStorageResourceFilter):
|
||||||
|
|
||||||
|
# The resource filters to be listed
|
||||||
|
fake_resource_filters = \
|
||||||
|
volume_fakes.FakeResourceFilter.create_resource_filters()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.resource_filter_mock.list.return_value = \
|
||||||
|
self.fake_resource_filters
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = block_storage_resource_filter\
|
||||||
|
.ListBlockStorageResourceFilter(self.app, None)
|
||||||
|
|
||||||
|
def test_resource_filter_list(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.33')
|
||||||
|
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
expected_columns = ('Resource', 'Filters')
|
||||||
|
expected_data = tuple(
|
||||||
|
(
|
||||||
|
resource_filter.resource,
|
||||||
|
resource_filter.filters,
|
||||||
|
) for resource_filter in self.fake_resource_filters
|
||||||
|
)
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
self.assertEqual(expected_data, tuple(data))
|
||||||
|
|
||||||
|
# checking if proper call was made to list clusters
|
||||||
|
self.resource_filter_mock.list.assert_called_with()
|
||||||
|
|
||||||
|
def test_resource_filter_list_pre_v333(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.32')
|
||||||
|
|
||||||
|
arglist = []
|
||||||
|
verifylist = []
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
exc = self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
self.assertIn(
|
||||||
|
'--os-volume-api-version 3.33 or greater is required', str(exc))
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlockStorageResourceFilterShow(TestBlockStorageResourceFilter):
|
||||||
|
|
||||||
|
# The resource filters to be listed
|
||||||
|
fake_resource_filter = \
|
||||||
|
volume_fakes.FakeResourceFilter.create_one_resource_filter()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
|
||||||
|
self.resource_filter_mock.list.return_value = \
|
||||||
|
iter([self.fake_resource_filter])
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = block_storage_resource_filter\
|
||||||
|
.ShowBlockStorageResourceFilter(self.app, None)
|
||||||
|
|
||||||
|
def test_resource_filter_show(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.33')
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.fake_resource_filter.resource,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('resource', self.fake_resource_filter.resource),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
expected_columns = ('filters', 'resource')
|
||||||
|
expected_data = (
|
||||||
|
self.fake_resource_filter.filters,
|
||||||
|
self.fake_resource_filter.resource,
|
||||||
|
)
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual(expected_columns, columns)
|
||||||
|
self.assertEqual(expected_data, data)
|
||||||
|
|
||||||
|
# checking if proper call was made to list clusters
|
||||||
|
self.resource_filter_mock.list.assert_called_with(resource='volume')
|
||||||
|
|
||||||
|
def test_resource_filter_show_pre_v333(self):
|
||||||
|
self.app.client_manager.volume.api_version = \
|
||||||
|
api_versions.APIVersion('3.32')
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
self.fake_resource_filter.resource,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('resource', self.fake_resource_filter.resource),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
exc = self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
self.assertIn(
|
||||||
|
'--os-volume-api-version 3.33 or greater is required', str(exc))
|
||||||
83
openstackclient/volume/v3/block_storage_resource_filter.py
Normal file
83
openstackclient/volume/v3/block_storage_resource_filter.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Volume V3 Resource Filters implementations"""
|
||||||
|
|
||||||
|
from cinderclient import api_versions
|
||||||
|
from osc_lib.command import command
|
||||||
|
from osc_lib import exceptions
|
||||||
|
from osc_lib import utils
|
||||||
|
|
||||||
|
from openstackclient.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
class ListBlockStorageResourceFilter(command.Lister):
|
||||||
|
_description = _('List block storage resource filters')
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
|
if volume_client.api_version < api_versions.APIVersion('3.33'):
|
||||||
|
msg = _(
|
||||||
|
"--os-volume-api-version 3.33 or greater is required to "
|
||||||
|
"support the 'block storage resource filter list' command"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
column_headers = (
|
||||||
|
'Resource',
|
||||||
|
'Filters',
|
||||||
|
)
|
||||||
|
|
||||||
|
data = volume_client.resource_filters.list()
|
||||||
|
|
||||||
|
return (
|
||||||
|
column_headers,
|
||||||
|
(utils.get_item_properties(s, column_headers) for s in data)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ShowBlockStorageResourceFilter(command.ShowOne):
|
||||||
|
_description = _('Show filters for a block storage resource type')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'resource',
|
||||||
|
metavar='<resource>',
|
||||||
|
help=_('Resource to show filters for (name).')
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
volume_client = self.app.client_manager.volume
|
||||||
|
|
||||||
|
if volume_client.api_version < api_versions.APIVersion('3.33'):
|
||||||
|
msg = _(
|
||||||
|
"--os-volume-api-version 3.33 or greater is required to "
|
||||||
|
"support the 'block storage resource filter show' command"
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
|
data = volume_client.resource_filters.list(
|
||||||
|
resource=parsed_args.resource
|
||||||
|
)
|
||||||
|
if not data:
|
||||||
|
msg = _(
|
||||||
|
"No resource filter with a name of {parsed_args.resource}' "
|
||||||
|
"exists."
|
||||||
|
)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
resource_filter = next(data)
|
||||||
|
|
||||||
|
return zip(*sorted(resource_filter._info.items()))
|
||||||
@@ -759,6 +759,8 @@ openstack.volume.v3 =
|
|||||||
block_storage_cluster_list = openstackclient.volume.v3.block_storage_cluster:ListBlockStorageCluster
|
block_storage_cluster_list = openstackclient.volume.v3.block_storage_cluster:ListBlockStorageCluster
|
||||||
block_storage_cluster_set = openstackclient.volume.v3.block_storage_cluster:SetBlockStorageCluster
|
block_storage_cluster_set = openstackclient.volume.v3.block_storage_cluster:SetBlockStorageCluster
|
||||||
block_storage_cluster_show = openstackclient.volume.v3.block_storage_cluster:ShowBlockStorageCluster
|
block_storage_cluster_show = openstackclient.volume.v3.block_storage_cluster:ShowBlockStorageCluster
|
||||||
|
block_storage_resource_filter_list = openstackclient.volume.v3.block_storage_resource_filter:ListBlockStorageResourceFilter
|
||||||
|
block_storage_resource_filter_show = openstackclient.volume.v3.block_storage_resource_filter:ShowBlockStorageResourceFilter
|
||||||
|
|
||||||
volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot
|
volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot
|
||||||
volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot
|
volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot
|
||||||
|
|||||||
Reference in New Issue
Block a user