Skip to content

Commit 644106a

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "volume: Add 'block storage resource filter list' command"
2 parents 7fcfce4 + 53a7e67 commit 644106a

File tree

7 files changed

+290
-5
lines changed

7 files changed

+290
-5
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=============================
2+
block storage resource filter
3+
=============================
4+
5+
Block Storage v3
6+
7+
.. autoprogram-cliff:: openstack.volume.v3
8+
:command: block storage resource filter *

doc/source/cli/commands.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ referring to both Compute and Volume quotas.
7777
* ``aggregate``: (**Compute**) a grouping of compute hosts
7878
* ``availability zone``: (**Compute**, **Network**, **Volume**) a logical partition of hosts or block storage or network services
7979
* ``block storage cluster``: (**Volume**) clusters of volume services
80+
* ``block storage resource filter``: (**Volume**) filters for volume service resources
8081
* ``catalog``: (**Identity**) service catalog
8182
* ``command``: (**Internal**) installed commands in the OSC process
8283
* ``compute agent``: (**Compute**) a cloud Compute agent available to a hypervisor

doc/source/cli/data/cinder.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ group-update,volume group set,Updates a group. (Supported by API versions 3.13 -
6969
image-metadata,volume set --image-property,Sets or deletes volume image metadata.
7070
image-metadata-show,volume show,Shows volume image metadata.
7171
list,volume list,Lists all volumes.
72-
list-filters,,List enabled filters. (Supported by API versions 3.33 - 3.latest)
72+
list-filters,block storage resource filter list,List enabled filters. (Supported by API versions 3.33 - 3.latest)
7373
manage,volume create --remote-source k=v,Manage an existing volume.
7474
manageable-list,,Lists all manageable volumes. (Supported by API versions 3.8 - 3.latest)
7575
message-delete,volume message delete,Removes one or more messages. (Supported by API versions 3.3 - 3.latest)

openstackclient/tests/unit/volume/v3/fakes.py

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ def __init__(self, **kwargs):
4242
self.group_types.resource_class = fakes.FakeResource(None, {})
4343
self.messages = mock.Mock()
4444
self.messages.resource_class = fakes.FakeResource(None, {})
45+
self.resource_filters = mock.Mock()
46+
self.resource_filters.resource_class = fakes.FakeResource(None, {})
4547
self.volumes = mock.Mock()
4648
self.volumes.resource_class = fakes.FakeResource(None, {})
4749
self.volume_types = mock.Mock()
@@ -124,6 +126,53 @@ def create_clusters(attrs=None, count=2):
124126
return clusters
125127

126128

129+
class FakeResourceFilter:
130+
"""Fake one or more resource filters."""
131+
132+
@staticmethod
133+
def create_one_resource_filter(attrs=None):
134+
"""Create a fake resource filter.
135+
136+
:param attrs: A dictionary with all attributes of resource filter
137+
:return: A FakeResource object with id, name, status, etc.
138+
"""
139+
attrs = attrs or {}
140+
141+
# Set default attribute
142+
143+
resource_filter_info = {
144+
'filters': [
145+
'name',
146+
'status',
147+
'image_metadata',
148+
'bootable',
149+
'migration_status',
150+
],
151+
'resource': 'volume',
152+
}
153+
154+
# Overwrite default attributes if there are some attributes set
155+
resource_filter_info.update(attrs)
156+
157+
return fakes.FakeResource(None, resource_filter_info, loaded=True)
158+
159+
@staticmethod
160+
def create_resource_filters(attrs=None, count=2):
161+
"""Create multiple fake resource filters.
162+
163+
:param attrs: A dictionary with all attributes of resource filter
164+
:param count: The number of resource filters to be faked
165+
:return: A list of FakeResource objects
166+
"""
167+
resource_filters = []
168+
for n in range(0, count):
169+
resource_filters.append(
170+
FakeResourceFilter.create_one_resource_filter(attrs)
171+
)
172+
173+
return resource_filters
174+
175+
127176
class FakeVolumeGroup:
128177
"""Fake one or more volume groups."""
129178

@@ -309,11 +358,10 @@ def create_one_volume_message(attrs=None):
309358
# Overwrite default attributes if there are some attributes set
310359
message_info.update(attrs)
311360

312-
message = fakes.FakeResource(
361+
return fakes.FakeResource(
313362
None,
314363
message_info,
315364
loaded=True)
316-
return message
317365

318366
@staticmethod
319367
def create_volume_messages(attrs=None, count=2):
@@ -402,11 +450,10 @@ def create_one_volume_attachment(attrs=None):
402450
# Overwrite default attributes if there are some attributes set
403451
attachment_info.update(attrs)
404452

405-
attachment = fakes.FakeResource(
453+
return fakes.FakeResource(
406454
None,
407455
attachment_info,
408456
loaded=True)
409-
return attachment
410457

411458
@staticmethod
412459
def create_volume_attachments(attrs=None, count=2):
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
from cinderclient import api_versions
14+
from osc_lib import exceptions
15+
16+
from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
17+
from openstackclient.volume.v3 import block_storage_resource_filter
18+
19+
20+
class TestBlockStorageResourceFilter(volume_fakes.TestVolume):
21+
22+
def setUp(self):
23+
super().setUp()
24+
25+
# Get a shortcut to the ResourceFilterManager Mock
26+
self.resource_filter_mock = \
27+
self.app.client_manager.volume.resource_filters
28+
self.resource_filter_mock.reset_mock()
29+
30+
31+
class TestBlockStorageResourceFilterList(TestBlockStorageResourceFilter):
32+
33+
# The resource filters to be listed
34+
fake_resource_filters = \
35+
volume_fakes.FakeResourceFilter.create_resource_filters()
36+
37+
def setUp(self):
38+
super().setUp()
39+
40+
self.resource_filter_mock.list.return_value = \
41+
self.fake_resource_filters
42+
43+
# Get the command object to test
44+
self.cmd = block_storage_resource_filter\
45+
.ListBlockStorageResourceFilter(self.app, None)
46+
47+
def test_resource_filter_list(self):
48+
self.app.client_manager.volume.api_version = \
49+
api_versions.APIVersion('3.33')
50+
51+
arglist = []
52+
verifylist = []
53+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
54+
55+
expected_columns = ('Resource', 'Filters')
56+
expected_data = tuple(
57+
(
58+
resource_filter.resource,
59+
resource_filter.filters,
60+
) for resource_filter in self.fake_resource_filters
61+
)
62+
columns, data = self.cmd.take_action(parsed_args)
63+
64+
self.assertEqual(expected_columns, columns)
65+
self.assertEqual(expected_data, tuple(data))
66+
67+
# checking if proper call was made to list clusters
68+
self.resource_filter_mock.list.assert_called_with()
69+
70+
def test_resource_filter_list_pre_v333(self):
71+
self.app.client_manager.volume.api_version = \
72+
api_versions.APIVersion('3.32')
73+
74+
arglist = []
75+
verifylist = []
76+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
77+
78+
exc = self.assertRaises(
79+
exceptions.CommandError,
80+
self.cmd.take_action,
81+
parsed_args)
82+
self.assertIn(
83+
'--os-volume-api-version 3.33 or greater is required', str(exc))
84+
85+
86+
class TestBlockStorageResourceFilterShow(TestBlockStorageResourceFilter):
87+
88+
# The resource filters to be listed
89+
fake_resource_filter = \
90+
volume_fakes.FakeResourceFilter.create_one_resource_filter()
91+
92+
def setUp(self):
93+
super().setUp()
94+
95+
self.resource_filter_mock.list.return_value = \
96+
iter([self.fake_resource_filter])
97+
98+
# Get the command object to test
99+
self.cmd = block_storage_resource_filter\
100+
.ShowBlockStorageResourceFilter(self.app, None)
101+
102+
def test_resource_filter_show(self):
103+
self.app.client_manager.volume.api_version = \
104+
api_versions.APIVersion('3.33')
105+
106+
arglist = [
107+
self.fake_resource_filter.resource,
108+
]
109+
verifylist = [
110+
('resource', self.fake_resource_filter.resource),
111+
]
112+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
113+
114+
expected_columns = ('filters', 'resource')
115+
expected_data = (
116+
self.fake_resource_filter.filters,
117+
self.fake_resource_filter.resource,
118+
)
119+
columns, data = self.cmd.take_action(parsed_args)
120+
121+
self.assertEqual(expected_columns, columns)
122+
self.assertEqual(expected_data, data)
123+
124+
# checking if proper call was made to list clusters
125+
self.resource_filter_mock.list.assert_called_with(resource='volume')
126+
127+
def test_resource_filter_show_pre_v333(self):
128+
self.app.client_manager.volume.api_version = \
129+
api_versions.APIVersion('3.32')
130+
131+
arglist = [
132+
self.fake_resource_filter.resource,
133+
]
134+
verifylist = [
135+
('resource', self.fake_resource_filter.resource),
136+
]
137+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
138+
139+
exc = self.assertRaises(
140+
exceptions.CommandError,
141+
self.cmd.take_action,
142+
parsed_args)
143+
self.assertIn(
144+
'--os-volume-api-version 3.33 or greater is required', str(exc))
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
"""Volume V3 Resource Filters implementations"""
14+
15+
from cinderclient import api_versions
16+
from osc_lib.command import command
17+
from osc_lib import exceptions
18+
from osc_lib import utils
19+
20+
from openstackclient.i18n import _
21+
22+
23+
class ListBlockStorageResourceFilter(command.Lister):
24+
_description = _('List block storage resource filters')
25+
26+
def take_action(self, parsed_args):
27+
volume_client = self.app.client_manager.volume
28+
29+
if volume_client.api_version < api_versions.APIVersion('3.33'):
30+
msg = _(
31+
"--os-volume-api-version 3.33 or greater is required to "
32+
"support the 'block storage resource filter list' command"
33+
)
34+
raise exceptions.CommandError(msg)
35+
36+
column_headers = (
37+
'Resource',
38+
'Filters',
39+
)
40+
41+
data = volume_client.resource_filters.list()
42+
43+
return (
44+
column_headers,
45+
(utils.get_item_properties(s, column_headers) for s in data)
46+
)
47+
48+
49+
class ShowBlockStorageResourceFilter(command.ShowOne):
50+
_description = _('Show filters for a block storage resource type')
51+
52+
def get_parser(self, prog_name):
53+
parser = super().get_parser(prog_name)
54+
parser.add_argument(
55+
'resource',
56+
metavar='<resource>',
57+
help=_('Resource to show filters for (name).')
58+
)
59+
60+
return parser
61+
62+
def take_action(self, parsed_args):
63+
volume_client = self.app.client_manager.volume
64+
65+
if volume_client.api_version < api_versions.APIVersion('3.33'):
66+
msg = _(
67+
"--os-volume-api-version 3.33 or greater is required to "
68+
"support the 'block storage resource filter show' command"
69+
)
70+
raise exceptions.CommandError(msg)
71+
72+
data = volume_client.resource_filters.list(
73+
resource=parsed_args.resource
74+
)
75+
if not data:
76+
msg = _(
77+
"No resource filter with a name of {parsed_args.resource}' "
78+
"exists."
79+
)
80+
raise exceptions.CommandError(msg)
81+
resource_filter = next(data)
82+
83+
return zip(*sorted(resource_filter._info.items()))

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,8 @@ openstack.volume.v3 =
759759
block_storage_cluster_list = openstackclient.volume.v3.block_storage_cluster:ListBlockStorageCluster
760760
block_storage_cluster_set = openstackclient.volume.v3.block_storage_cluster:SetBlockStorageCluster
761761
block_storage_cluster_show = openstackclient.volume.v3.block_storage_cluster:ShowBlockStorageCluster
762+
block_storage_resource_filter_list = openstackclient.volume.v3.block_storage_resource_filter:ListBlockStorageResourceFilter
763+
block_storage_resource_filter_show = openstackclient.volume.v3.block_storage_resource_filter:ShowBlockStorageResourceFilter
762764

763765
volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot
764766
volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot

0 commit comments

Comments
 (0)