diff --git a/manila/api/openstack/api_version_request.py b/manila/api/openstack/api_version_request.py index 841fb2de..e7f1cd03 100644 --- a/manila/api/openstack/api_version_request.py +++ b/manila/api/openstack/api_version_request.py @@ -100,13 +100,15 @@ REST_API_VERSION_HISTORY = """ * 2.32 - Added mountable snapshots APIs. * 2.33 - Added 'created_at' and 'updated_at' to the response of access_list API. + * 2.34 - Added 'availability_zone_id' and 'consistent_snapshot_support' + fields to 'share_group' object. """ # The minimum and maximum versions of the API supported # The default api version request is defined to be the # minimum version of the API supported. _MIN_API_VERSION = "2.0" -_MAX_API_VERSION = "2.33" +_MAX_API_VERSION = "2.34" DEFAULT_API_VERSION = _MIN_API_VERSION diff --git a/manila/api/openstack/rest_api_version_history.rst b/manila/api/openstack/rest_api_version_history.rst index 710e20d6..acc62b5a 100644 --- a/manila/api/openstack/rest_api_version_history.rst +++ b/manila/api/openstack/rest_api_version_history.rst @@ -195,3 +195,8 @@ user documentation. 2.33 ---- Added created_at and updated_at in access_list API. + +2.34 +---- + Added 'availability_zone_id' and 'consistent_snapshot_support' fields to + 'share_group' object. diff --git a/manila/api/views/share_groups.py b/manila/api/views/share_groups.py index 1a82a300..510f73d2 100644 --- a/manila/api/views/share_groups.py +++ b/manila/api/views/share_groups.py @@ -20,6 +20,9 @@ class ShareGroupViewBuilder(common.ViewBuilder): """Model a share group API response as a python dictionary.""" _collection_name = 'share_groups' + _detail_version_modifiers = [ + "add_consistent_snapshot_support_and_az_id_fields_to_sg", + ] def summary_list(self, request, share_groups): """Show a list of share groups without many details.""" @@ -57,13 +60,21 @@ class ShareGroupViewBuilder(common.ViewBuilder): 'share_types': [st['share_type_id'] for st in share_group.get( 'share_types')], 'links': self._get_links(request, share_group['id']), - # TODO(vponomaryov): add 'consistent_snapshot_support' key in Pike. } + self.update_versioned_resource_dict( + request, share_group_dict, share_group) if context.is_admin: share_group_dict['share_server_id'] = share_group.get( 'share_server_id') return {'share_group': share_group_dict} + @common.ViewBuilder.versioned_method("2.34") + def add_consistent_snapshot_support_and_az_id_fields_to_sg( + self, context, sg_dict, sg): + sg_dict['availability_zone'] = sg.get('availability_zone') + sg_dict['consistent_snapshot_support'] = sg.get( + 'consistent_snapshot_support') + def _list_view(self, func, request, shares): """Provide a view for a list of share groups.""" share_group_list = [ diff --git a/manila/tests/api/v2/test_share_groups.py b/manila/tests/api/v2/test_share_groups.py index 947df003..96562458 100644 --- a/manila/tests/api/v2/test_share_groups.py +++ b/manila/tests/api/v2/test_share_groups.py @@ -53,7 +53,7 @@ class ShareGroupAPITest(test.TestCase): self.fake_share_type = {'id': six.text_type(uuidutils.generate_uuid())} self.fake_share_group_type = { 'id': six.text_type(uuidutils.generate_uuid())} - self.api_version = '2.31' + self.api_version = '2.34' self.request = fakes.HTTPRequest.blank( '/share-groups', version=self.api_version, experimental=True) self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake') @@ -94,7 +94,8 @@ class ShareGroupAPITest(test.TestCase): 'name': None, 'description': None, 'host': None, - 'availability_zone_id': None, + 'availability_zone': None, + 'consistent_snapshot_support': None, 'source_share_group_snapshot_id': None, 'share_group_type_id': self.fake_share_group_type.get('id'), 'share_network_id': uuidutils.generate_uuid(), @@ -112,10 +113,9 @@ class ShareGroupAPITest(test.TestCase): 'name': share_group_db_dict['name'], 'description': share_group_db_dict['description'], 'host': share_group_db_dict['host'], - # NOTE(vponomaryov): uncomment following when API start returning - # availability zone value. - # 'availability_zone_id': share_group_db_dict[ - # 'availability_zone_id'], + 'availability_zone': share_group_db_dict['availability_zone'], + 'consistent_snapshot_support': share_group_db_dict[ + 'consistent_snapshot_support'], 'source_share_group_snapshot_id': share_group_db_dict[ 'source_share_group_snapshot_id'], 'share_group_type_id': share_group_db_dict['share_group_type_id'], diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py index 3be873f6..e54dd483 100644 --- a/manila_tempest_tests/config.py +++ b/manila_tempest_tests/config.py @@ -30,7 +30,7 @@ ShareGroup = [ help="The minimum api microversion is configured to be the " "value of the minimum microversion supported by Manila."), cfg.StrOpt("max_api_microversion", - default="2.33", + default="2.34", help="The maximum api microversion is configured to be the " "value of the latest microversion supported by Manila."), cfg.StrOpt("region", diff --git a/manila_tempest_tests/tests/api/test_share_groups.py b/manila_tempest_tests/tests/api/test_share_groups.py index 98d29e4e..68ff6470 100644 --- a/manila_tempest_tests/tests/api/test_share_groups.py +++ b/manila_tempest_tests/tests/api/test_share_groups.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import ddt from tempest import config from tempest.lib import exceptions as lib_exc import testtools @@ -27,6 +28,7 @@ CONF = config.CONF @testtools.skipUnless( CONF.share.run_share_group_tests, 'Share Group tests disabled.') @base.skip_if_microversion_lt(constants.MIN_SHARE_GROUP_MICROVERSION) +@ddt.ddt class ShareGroupsTest(base.BaseSharesTest): """Covers share group functionality.""" @@ -163,3 +165,58 @@ class ShareGroupsTest(base.BaseSharesTest): share_group['share_network_id'], new_share_group['share_network_id'], msg) + + @base.skip_if_microversion_lt("2.34") + @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND) + @ddt.data( + 'sg', 'sg_and_share', 'none', + ) + def test_create_sg_and_share_specifying_az(self, where_specify_az): + # Get list of existing availability zones, at least one always + # should exist + azs = self.shares_v2_client.list_availability_zones() + + sg_kwargs = { + 'version': '2.34', + 'cleanup_in_class': False, + } + if where_specify_az in ('sg', 'sg_and_share'): + sg_kwargs['availability_zone'] = azs[0]['name'] + + # Create share group + share_group = self.create_share_group(**sg_kwargs) + + # Get latest share group info + share_group = self.shares_v2_client.get_share_group( + share_group['id'], '2.34') + + self.assertIn('availability_zone', share_group) + if where_specify_az in ('sg', 'sg_and_share'): + self.assertEqual(azs[0]['name'], share_group['availability_zone']) + else: + self.assertIn( + share_group['availability_zone'], [az['name'] for az in azs]) + + # Test 'consistent_snapshot_support' as part of 2.33 API change + self.assertIn('consistent_snapshot_support', share_group) + self.assertIn( + share_group['consistent_snapshot_support'], ('host', 'pool', None)) + + s_kwargs = { + 'share_group_id': share_group['id'], + 'version': '2.33', + 'cleanup_in_class': False, + 'experimental': True, + } + if where_specify_az == 'sg_and_share': + s_kwargs['availability_zone'] = azs[0]['name'] + + # Create share in share group + share = self.create_share(**s_kwargs) + + # Get latest share info + share = self.shares_v2_client.get_share(share['id'], '2.34') + + # Verify that share always has the same AZ as share group does + self.assertEqual( + share_group['availability_zone'], share['availability_zone']) diff --git a/manila_tempest_tests/tests/api/test_share_groups_negative.py b/manila_tempest_tests/tests/api/test_share_groups_negative.py index b33eca92..af29879c 100644 --- a/manila_tempest_tests/tests/api/test_share_groups_negative.py +++ b/manila_tempest_tests/tests/api/test_share_groups_negative.py @@ -237,3 +237,37 @@ class ShareGroupsNegativeTest(base.BaseSharesTest): version=constants.MIN_SHARE_GROUP_MICROVERSION, ) self.assertEqual(0, len(shares), 'Incorrect number of shares returned') + + @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND) + def test_create_sg_with_nonexistent_az_min(self): + self.assertRaises( + lib_exc.NotFound, + self.shares_v2_client.create_share_group, + name='tempest_sg', + description='tempest_sg_desc', + availability_zone='fake_nonexistent_az', + version=constants.MIN_SHARE_GROUP_MICROVERSION) + + @base.skip_if_microversion_lt("2.34") + @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND) + def test_create_sg_and_share_with_different_azs(self): + azs = self.shares_v2_client.list_availability_zones() + + if len(azs) < 2: + raise self.skipException( + 'Test requires presence of at least 2 availability zones.') + else: + share_group = self.shares_v2_client.get_share_group( + self.share_group['id'], '2.34') + different_az = [ + az['name'] + for az in azs + if az['name'] != share_group['availability_zone'] + ][0] + + self.assertRaises( + lib_exc.BadRequest, + self.create_share, + share_group_id=self.share_group['id'], + availability_zone=different_az, + version='2.34') diff --git a/releasenotes/notes/add-two-new-fields-to-share-groups-api-bc576dddd58a3086.yaml b/releasenotes/notes/add-two-new-fields-to-share-groups-api-bc576dddd58a3086.yaml new file mode 100644 index 00000000..acbf8fff --- /dev/null +++ b/releasenotes/notes/add-two-new-fields-to-share-groups-api-bc576dddd58a3086.yaml @@ -0,0 +1,5 @@ +--- +features: + - added two new fields to share groups API - 'availability_zone_id' and + 'consistent_snapshot_support' to be able to get to know these attributes + of a share group.