Browse Source

Add update share-type to SDK and CLI

Currently, only the name and description and public access of share-type
is set when the share-type is created, and not allowed to be edited
after the share-type is created. We can only set extra spec for share-type.
But not name or description or public access for share-type.

Change-Id: Ia0df0d46e11d0438e16fc910fc377f9dd4e85521
Partially-Implements: blueprint update-share-type-name-or-description
Depends-On: https://review.opendev.org/669651
tags/1.29.0
haixin 2 months ago
parent
commit
cc401e5333

+ 1
- 1
manilaclient/api_versions.py View File

@@ -27,7 +27,7 @@ from manilaclient import utils
27 27
 
28 28
 LOG = logging.getLogger(__name__)
29 29
 
30
-MAX_VERSION = '2.49'
30
+MAX_VERSION = '2.50'
31 31
 MIN_VERSION = '2.0'
32 32
 DEPRECATED_VERSION = '1.0'
33 33
 _VERSIONED_METHOD_MAP = {}

+ 19
- 0
manilaclient/tests/functional/base.py View File

@@ -211,6 +211,25 @@ class BaseTestCase(base.ClientTestBase):
211 211
             cls.method_resources.insert(0, resource)
212 212
         return share_type
213 213
 
214
+    @classmethod
215
+    def update_share_type(cls, share_type_id, name=None,
216
+                          is_public=None, client=None,
217
+                          microversion=None, description=None):
218
+        if client is None:
219
+            client = cls.get_admin_client()
220
+        data = {
221
+            "share_type_id": share_type_id,
222
+            "microversion": microversion,
223
+        }
224
+        if name is not None:
225
+            data["name"] = name
226
+        if description is not None:
227
+            data["description"] = description
228
+        if is_public is not None:
229
+            data["is_public"] = is_public
230
+        share_type = client.update_share_type(**data)
231
+        return share_type
232
+
214 233
     @classmethod
215 234
     def create_share_network(cls, name=None, description=None,
216 235
                              neutron_net_id=None,

+ 35
- 0
manilaclient/tests/functional/client.py View File

@@ -244,6 +244,41 @@ class ManilaCLIClient(base.CLIClient):
244 244
         share_type = utils.details(share_type_raw)
245 245
         return share_type
246 246
 
247
+    def update_share_type(self, share_type_id, name=None,
248
+                          is_public=None, microversion=None,
249
+                          description=None):
250
+        """Update share type.
251
+
252
+        :param share_type_id: text -- id of share type.
253
+        :param name: text -- new name of share type, if not set then
254
+            it will not be updated.
255
+        :param description: text -- new description of share type.
256
+            if not set then it will not be updated.
257
+        :param is_public: bool/str -- boolean or its string alias.
258
+            new visibility of the share type.If set to True, share
259
+            type will be available to all projects in the cloud.
260
+        """
261
+
262
+        cmd = ('type-update %(share_type_id)s ') % {
263
+            'share_type_id': share_type_id}
264
+
265
+        if is_public is not None:
266
+            if not isinstance(is_public, six.string_types):
267
+                is_public = six.text_type(is_public)
268
+            cmd += " --is_public " + is_public
269
+
270
+        if description:
271
+            cmd += " --description " + description
272
+        elif description == "":
273
+            cmd += ' --description "" '
274
+
275
+        if name:
276
+            cmd += " --name " + name
277
+
278
+        share_type_raw = self.manila(cmd, microversion=microversion)
279
+        share_type = utils.details(share_type_raw)
280
+        return share_type
281
+
247 282
     @not_found_wrapper
248 283
     def delete_share_type(self, share_type, microversion=None):
249 284
         """Deletes share type by its Name or ID."""

+ 102
- 0
manilaclient/tests/functional/test_share_types.py View File

@@ -122,6 +122,108 @@ class ShareTypesReadWriteTest(base.BaseTestCase):
122 122
             '2.41', True, False, None, None, None, None, None,
123 123
             description=data_utils.rand_name('test_share_type_description'))
124 124
 
125
+    @ddt.data(
126
+        ('name_updated_1', 'description_updated', True),
127
+        ('name_updated_2', 'description_updated', False),
128
+        ('name_updated_3', None, None),
129
+        (None, 'description_updated', None),
130
+        (None, None, True),
131
+        (None, None, False),
132
+    )
133
+    @ddt.unpack
134
+    def test_create_update_delete_share_type_2_50(self, new_name,
135
+                                                  new_description,
136
+                                                  new_is_public):
137
+        self.skip_if_microversion_not_supported('2.50')
138
+        microversion = '2.50'
139
+        share_type_name = data_utils.rand_name('share_type_update_test')
140
+
141
+        # Create share type
142
+        share_type = self.create_share_type(
143
+            name=share_type_name,
144
+            driver_handles_share_servers=False,
145
+            snapshot_support=None,
146
+            create_share_from_snapshot=None,
147
+            revert_to_snapshot=None,
148
+            mount_snapshot=None,
149
+            is_public=True,
150
+            microversion=microversion,
151
+            extra_specs={},
152
+            description="share_type_description")
153
+
154
+        st_id = share_type['ID']
155
+
156
+        # Update share type
157
+        st_updated = self.update_share_type(st_id, name=new_name,
158
+                                            description=new_description,
159
+                                            is_public=new_is_public,
160
+                                            microversion=microversion)
161
+        # Verify type name
162
+        if new_name:
163
+            self.assertEqual(new_name, st_updated['Name'])
164
+
165
+        # Verify type description
166
+        if new_description:
167
+            self.assertEqual(new_description, st_updated['Description'])
168
+
169
+        # Verify public
170
+        if new_is_public is not None:
171
+            self.assertEqual('public' if new_is_public else 'private',
172
+                             st_updated['Visibility'].lower())
173
+
174
+        # Delete share type
175
+        self.admin_client.delete_share_type(st_id, microversion=microversion)
176
+
177
+        # Wait for share type deletion
178
+        self.admin_client.wait_for_share_type_deletion(
179
+            st_id, microversion=microversion)
180
+
181
+        # Verify that it is not listed with common 'type-list' operation.
182
+        share_types = self.admin_client.list_share_types(
183
+            list_all=False, microversion=microversion)
184
+        self.assertFalse(any(st_id == st['ID'] for st in share_types))
185
+
186
+    def test_unset_share_type_description_2_50(self):
187
+        self.skip_if_microversion_not_supported('2.50')
188
+        microversion = '2.50'
189
+        share_type_name = data_utils.rand_name('share_type_update_test')
190
+
191
+        # Create share type
192
+        share_type = self.create_share_type(
193
+            name=share_type_name,
194
+            driver_handles_share_servers=False,
195
+            snapshot_support=None,
196
+            create_share_from_snapshot=None,
197
+            revert_to_snapshot=None,
198
+            mount_snapshot=None,
199
+            is_public=True,
200
+            microversion=microversion,
201
+            extra_specs={},
202
+            description="share_type_description")
203
+
204
+        st_id = share_type['ID']
205
+
206
+        # Update share type
207
+        new_description = ""
208
+        st_updated = self.update_share_type(st_id,
209
+                                            description=new_description,
210
+                                            microversion=microversion)
211
+
212
+        # Verify type description
213
+        self.assertEqual('None', st_updated['Description'])
214
+
215
+        # Delete share type
216
+        self.admin_client.delete_share_type(st_id, microversion=microversion)
217
+
218
+        # Wait for share type deletion
219
+        self.admin_client.wait_for_share_type_deletion(
220
+            st_id, microversion=microversion)
221
+
222
+        # Verify that it is not listed with common 'type-list' operation.
223
+        share_types = self.admin_client.list_share_types(
224
+            list_all=False, microversion=microversion)
225
+        self.assertFalse(any(st_id == st['ID'] for st in share_types))
226
+
125 227
     def _test_create_delete_share_type(self, microversion, is_public, dhss,
126 228
                                        spec_snapshot_support,
127 229
                                        spec_create_share_from_snapshot,

+ 3
- 2
manilaclient/tests/unit/v2/fakes.py View File

@@ -925,8 +925,9 @@ class FakeHTTPClient(fakes.FakeHTTPClient):
925 925
 
926 926
     def get_types_1234(self, **kw):
927 927
         return (200, {}, {
928
-            'share_type': {'id': 1,
929
-                           'name': 'test-type-1',
928
+            'share_type': {'id': 1234,
929
+                           'name': 'test-type-1234',
930
+                           'share_type_access:is_public': True,
930 931
                            'description': "test share type desc",
931 932
                            'extra_specs': {'test': 'test'},
932 933
                            'required_extra_specs': {'test': 'test'}}})

+ 27
- 0
manilaclient/tests/unit/v2/test_types.py View File

@@ -17,6 +17,7 @@ import itertools
17 17
 import mock
18 18
 
19 19
 from manilaclient import api_versions
20
+from manilaclient import config
20 21
 from manilaclient import exceptions
21 22
 from manilaclient.tests.unit import utils
22 23
 from manilaclient.tests.unit.v2 import fakes
@@ -24,6 +25,10 @@ from manilaclient.v2 import share_types
24 25
 
25 26
 cs = fakes.FakeClient()
26 27
 
28
+CONF = config.CONF
29
+
30
+LATEST_MICROVERSION = CONF.max_api_microversion
31
+
27 32
 
28 33
 def get_valid_type_create_data_2_0():
29 34
 
@@ -430,6 +435,28 @@ class TypesTest(utils.TestCase):
430 435
         t.unset_keys(['k'])
431 436
         cs.assert_called('DELETE', '/types/1/extra_specs/k')
432 437
 
438
+    @ddt.data(*set(('2.50', LATEST_MICROVERSION)))
439
+    def test_update(self, microversion):
440
+        manager = self._get_share_types_manager(microversion)
441
+        self.mock_object(manager, '_update', mock.Mock(return_value="fake"))
442
+        share_type = 1234
443
+        name = "updated-test-type-1234"
444
+        description = "updated test description"
445
+        is_public_key_name = "share_type_access:is_public"
446
+        is_public = False
447
+        expected_body = {
448
+            "share_type": {
449
+                "name": name,
450
+                is_public_key_name: is_public,
451
+            }
452
+        }
453
+        result = manager.update(
454
+            share_type, name, is_public, description)
455
+        expected_body['share_type']['description'] = description
456
+        manager._update.assert_called_once_with(
457
+            "/types/%s" % share_type, expected_body, "share_type")
458
+        self.assertEqual("fake", result)
459
+
433 460
     def test_delete(self):
434 461
         cs.share_types.delete(1)
435 462
         cs.assert_called('DELETE', '/types/1')

+ 33
- 0
manilaclient/v2/share_types.py View File

@@ -101,6 +101,10 @@ class ShareType(common_base.Resource):
101 101
             if resp is not None:
102 102
                 return resp
103 103
 
104
+    def update(self, **kwargs):
105
+        """Update this share type."""
106
+        return self.manager.update(self, **kwargs)
107
+
104 108
 
105 109
 class ShareTypeManager(base.ManagerWithFind):
106 110
     """Manage :class:`ShareType` resources."""
@@ -164,6 +168,30 @@ class ShareTypeManager(base.ManagerWithFind):
164 168
             body["share_type"]["description"] = description
165 169
         return self._create("/types", body, "share_type")
166 170
 
171
+    def _do_update(self, share_type, name=None, is_public=None,
172
+                   is_public_keyname="share_type_access:is_public",
173
+                   description=None):
174
+        """Update the name and/or description for a share type.
175
+
176
+        :param share_type: the ID of the :class: `ShareType` to update.
177
+        :param name: Descriptive name of the share type.
178
+        :param description: Description of the share type.
179
+        :rtype: :class:`ShareType`
180
+        """
181
+
182
+        body = {
183
+            "share_type": {}
184
+        }
185
+
186
+        if name:
187
+            body["share_type"]["name"] = name
188
+        if is_public is not None:
189
+            body["share_type"][is_public_keyname] = is_public
190
+        if description or description == "":
191
+            body["share_type"]["description"] = description
192
+        return self._update("/types/%s" % common_base.getid(share_type),
193
+                            body, "share_type")
194
+
167 195
     @api_versions.wraps("1.0", "2.6")
168 196
     def create(self, name, spec_driver_handles_share_servers,
169 197
                spec_snapshot_support=None, is_public=True, extra_specs=None):
@@ -221,6 +249,11 @@ class ShareTypeManager(base.ManagerWithFind):
221 249
         return self._do_create(name, extra_specs, is_public,
222 250
                                description=description)
223 251
 
252
+    @api_versions.wraps("2.50")
253
+    def update(self, share_type, name=None, is_public=None, description=None):
254
+        return self._do_update(share_type, name, is_public,
255
+                               description=description)
256
+
224 257
     def _handle_spec_driver_handles_share_servers(
225 258
             self, extra_specs, spec_driver_handles_share_servers):
226 259
         """Validation and default for DHSS extra spec."""

+ 49
- 0
manilaclient/v2/shell.py View File

@@ -4131,6 +4131,55 @@ def do_type_create(cs, args):
4131 4131
     _print_share_type(stype, show_des=show_des)
4132 4132
 
4133 4133
 
4134
+@cliutils.arg(
4135
+    'id',
4136
+    metavar='<id>',
4137
+    help="Name or ID of the share type to update.")
4138
+@cliutils.arg(
4139
+    '--name',
4140
+    metavar='<name>',
4141
+    type=str,
4142
+    help="New name of share type.")
4143
+@cliutils.arg(
4144
+    '--description',
4145
+    metavar='<description>',
4146
+    type=str,
4147
+    default=None,
4148
+    help="New description of share type.")
4149
+@cliutils.arg(
4150
+    '--is-public',
4151
+    '--is_public',
4152
+    metavar='<is_public>',
4153
+    action='single_alias',
4154
+    help="New visibility of the share type. If set to True, share type will "
4155
+         "be available to all projects in the cloud.")
4156
+@api_versions.wraps("2.50")
4157
+def do_type_update(cs, args):
4158
+    """Update share type name, description, and/or visibility. (Admin only)."""
4159
+    name = getattr(args, 'name')
4160
+    description = getattr(args, 'description')
4161
+    is_public = getattr(args, 'is_public')
4162
+    if not name and description is None and is_public is None:
4163
+        msg = ("A description and/or non-empty name and/or boolean is_public "
4164
+               "must be supplied to update the respective attributes of the "
4165
+               "share type.")
4166
+        raise exceptions.CommandError(msg)
4167
+    kwargs = {}
4168
+    kwargs['name'] = name
4169
+    if is_public:
4170
+        try:
4171
+            kwargs['is_public'] = strutils.bool_from_string(is_public,
4172
+                                                            strict=True)
4173
+        except ValueError as e:
4174
+            raise exceptions.CommandError("The value of 'is_public' is"
4175
+                                          " invalid: %s", six.text_type(e))
4176
+
4177
+    kwargs['description'] = description
4178
+    stype = _find_share_type(cs, args.id)
4179
+    stype = stype.update(**kwargs)
4180
+    _print_share_type(stype, show_des=True)
4181
+
4182
+
4134 4183
 @cliutils.arg(
4135 4184
     'id',
4136 4185
     metavar='<id>',

+ 6
- 0
releasenotes/notes/bp-update-share-type-name-or-description-32d98b5a42cd8090.yaml View File

@@ -0,0 +1,6 @@
1
+---
2
+features:
3
+  - |
4
+    The ``name``, ``description`` and/or ``share_type_access:is_public``
5
+    attributes of share types can be updated with API version ``2.50``
6
+    and beyond.

Loading…
Cancel
Save