Browse Source

Add volume backend pool list command

Adds an equivalent for "cinder get-pools" with "volume backend pool list"
and "cinder get-pools --detail" with "volume backend pool list --long".

Story: 1655624
Task: 136949

Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
Change-Id: I826c9946ffe11340d44ad57914f72fc2a72b6938
Sean McGinnis 7 months ago
parent
commit
9647d43bd5
No account linked to committer's email address

+ 1
- 1
doc/source/cli/data/cinder.csv View File

@@ -33,7 +33,7 @@ failover-host,volume host failover,Failover a replicating cinder-volume host.
33 33
 force-delete,volume delete --force,"Attempts force-delete of volume, regardless of state."
34 34
 freeze-host,volume host set --disable,Freeze and disable the specified cinder-volume host.
35 35
 get-capabilities,volume backend capability show,Show capabilities of a volume backend. Admin only.
36
-get-pools,,Show pool information for backends. Admin only.
36
+get-pools,volume backend pool list,Show pool information for backends. Admin only.
37 37
 image-metadata,volume set --image-property,Sets or deletes volume image metadata.
38 38
 image-metadata-show,volume show,Shows volume image metadata.
39 39
 list,volume list,Lists all volumes.

+ 37
- 0
openstackclient/tests/unit/volume/v2/fakes.py View File

@@ -252,6 +252,41 @@ class FakeCapability(object):
252 252
         return capability
253 253
 
254 254
 
255
+class FakePool(object):
256
+    """Fake Pools."""
257
+
258
+    @staticmethod
259
+    def create_one_pool(attrs=None):
260
+        """Create a fake pool.
261
+
262
+        :param Dictionary attrs:
263
+            A dictionary with all attributes of the pool
264
+        :return:
265
+            A FakeResource object with pool name and attrs.
266
+        """
267
+        # Set default attribute
268
+        pool_info = {
269
+            'name': 'host@lvmdriver-1#lvmdriver-1',
270
+            'storage_protocol': 'iSCSI',
271
+            'thick_provisioning_support': False,
272
+            'thin_provisioning_support': True,
273
+            'total_volumes': 99,
274
+            'total_capacity_gb': 1000.00,
275
+            'allocated_capacity_gb': 100,
276
+            'max_over_subscription_ratio': 200.0,
277
+        }
278
+
279
+        # Overwrite default attributes if there are some attributes set
280
+        pool_info.update(attrs or {})
281
+
282
+        pool = fakes.FakeResource(
283
+            None,
284
+            pool_info,
285
+            loaded=True)
286
+
287
+        return pool
288
+
289
+
255 290
 class FakeVolumeClient(object):
256 291
 
257 292
     def __init__(self, **kwargs):
@@ -294,6 +329,8 @@ class FakeVolumeClient(object):
294 329
         self.management_url = kwargs['endpoint']
295 330
         self.capabilities = mock.Mock()
296 331
         self.capabilities.resource_class = fakes.FakeResource(None, {})
332
+        self.pools = mock.Mock()
333
+        self.pools.resource_class = fakes.FakeResource(None, {})
297 334
 
298 335
 
299 336
 class TestVolume(utils.TestCommand):

+ 95
- 0
openstackclient/tests/unit/volume/v2/test_volume_backend.py View File

@@ -71,3 +71,98 @@ class TestShowVolumeCapability(volume_fakes.TestVolume):
71 71
         self.capability_mock.get.assert_called_with(
72 72
             'fake',
73 73
         )
74
+
75
+
76
+class TestListVolumePool(volume_fakes.TestVolume):
77
+    """Tests for volume backend pool listing."""
78
+
79
+    # The pool to be listed
80
+    pools = volume_fakes.FakePool.create_one_pool()
81
+
82
+    def setUp(self):
83
+        super(TestListVolumePool, self).setUp()
84
+
85
+        self.pool_mock = self.app.client_manager.volume.pools
86
+        self.pool_mock.list.return_value = [self.pools]
87
+
88
+        # Get the command object to test
89
+        self.cmd = volume_backend.ListPool(self.app, None)
90
+
91
+    def test_pool_list(self):
92
+        arglist = []
93
+        verifylist = []
94
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
95
+
96
+        # In base command class Lister in cliff, abstract method take_action()
97
+        # returns a tuple containing the column names and an iterable
98
+        # containing the data to be listed.
99
+        columns, data = self.cmd.take_action(parsed_args)
100
+
101
+        expected_columns = [
102
+            'Name',
103
+        ]
104
+
105
+        # confirming if all expected columns are present in the result.
106
+        self.assertEqual(expected_columns, columns)
107
+
108
+        datalist = ((
109
+            self.pools.name,
110
+        ), )
111
+
112
+        # confirming if all expected values are present in the result.
113
+        self.assertEqual(datalist, tuple(data))
114
+
115
+        # checking if proper call was made to list pools
116
+        self.pool_mock.list.assert_called_with(
117
+            detailed=False,
118
+        )
119
+
120
+        # checking if long columns are present in output
121
+        self.assertNotIn("total_volumes", columns)
122
+        self.assertNotIn("storage_protocol", columns)
123
+
124
+    def test_service_list_with_long_option(self):
125
+        arglist = [
126
+            '--long'
127
+        ]
128
+        verifylist = [
129
+            ('long', True)
130
+        ]
131
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
132
+
133
+        # In base command class Lister in cliff, abstract method take_action()
134
+        # returns a tuple containing the column names and an iterable
135
+        # containing the data to be listed.
136
+        columns, data = self.cmd.take_action(parsed_args)
137
+
138
+        expected_columns = [
139
+            'Name',
140
+            'Protocol',
141
+            'Thick',
142
+            'Thin',
143
+            'Volumes',
144
+            'Capacity',
145
+            'Allocated',
146
+            'Max Over Ratio',
147
+        ]
148
+
149
+        # confirming if all expected columns are present in the result.
150
+        self.assertEqual(expected_columns, columns)
151
+
152
+        datalist = ((
153
+            self.pools.name,
154
+            self.pools.storage_protocol,
155
+            self.pools.thick_provisioning_support,
156
+            self.pools.thin_provisioning_support,
157
+            self.pools.total_volumes,
158
+            self.pools.total_capacity_gb,
159
+            self.pools.allocated_capacity_gb,
160
+            self.pools.max_over_subscription_ratio,
161
+        ), )
162
+
163
+        # confirming if all expected values are present in the result.
164
+        self.assertEqual(datalist, tuple(data))
165
+
166
+        self.pool_mock.list.assert_called_with(
167
+            detailed=True,
168
+        )

+ 53
- 1
openstackclient/volume/v2/volume_backend.py View File

@@ -12,7 +12,7 @@
12 12
 #   under the License.
13 13
 #
14 14
 
15
-"""Capability action implementations"""
15
+"""Storage backend action implementations"""
16 16
 
17 17
 from osc_lib.command import command
18 18
 from osc_lib import utils
@@ -59,3 +59,55 @@ class ShowCapability(command.Lister):
59 59
                 (utils.get_dict_properties(
60 60
                     s, columns,
61 61
                 ) for s in print_data))
62
+
63
+
64
+class ListPool(command.Lister):
65
+    _description = _("List pool command")
66
+
67
+    def get_parser(self, prog_name):
68
+        parser = super(ListPool, self).get_parser(prog_name)
69
+        parser.add_argument(
70
+            "--long",
71
+            action="store_true",
72
+            default=False,
73
+            help=_("Show detailed information about pools.")
74
+        )
75
+        # TODO(smcginnis): Starting with Cinder microversion 3.33, user is also
76
+        # able to pass in --filters with a <key>=<value> pair to filter on.
77
+        return parser
78
+
79
+    def take_action(self, parsed_args):
80
+        volume_client = self.app.client_manager.volume
81
+
82
+        if parsed_args.long:
83
+            columns = [
84
+                'name',
85
+                'storage_protocol',
86
+                'thick_provisioning_support',
87
+                'thin_provisioning_support',
88
+                'total_volumes',
89
+                'total_capacity_gb',
90
+                'allocated_capacity_gb',
91
+                'max_over_subscription_ratio',
92
+            ]
93
+            headers = [
94
+                'Name',
95
+                'Protocol',
96
+                'Thick',
97
+                'Thin',
98
+                'Volumes',
99
+                'Capacity',
100
+                'Allocated',
101
+                'Max Over Ratio'
102
+            ]
103
+        else:
104
+            columns = [
105
+                'Name',
106
+            ]
107
+            headers = columns
108
+
109
+        data = volume_client.pools.list(detailed=parsed_args.long)
110
+        return (headers,
111
+                (utils.get_item_properties(
112
+                    s, columns,
113
+                ) for s in data))

+ 4
- 0
releasenotes/notes/volume-backend-c5faae0b31556a24.yaml View File

@@ -5,3 +5,7 @@ features:
5 5
     added which will provide a list of all capabilities that can be configured
6 6
     for the requested backend. The required `<host>` parameter takes the form
7 7
     `host@backend-name`.
8
+  - |
9
+    A new command, ``openstack volume backend pool list`` was added which will
10
+    provide a list of all backend storage pools. The optional ``-long``
11
+    parameter includes some basic configuration and stats for each pool.

+ 1
- 0
setup.cfg View File

@@ -630,6 +630,7 @@ openstack.volume.v2 =
630 630
     volume_backup_show = openstackclient.volume.v2.backup:ShowVolumeBackup
631 631
 
632 632
     volume_backend_capability_show = openstackclient.volume.v2.volume_backend:ShowCapability
633
+    volume_backend_pool_list = openstackclient.volume.v2.volume_backend:ListPool
633 634
 
634 635
     volume_host_failover = openstackclient.volume.v2.volume_host:FailoverVolumeHost
635 636
     volume_host_set = openstackclient.volume.v2.volume_host:SetVolumeHost

Loading…
Cancel
Save