[Share Groups] Add two new fields to SG API object
Previous change [1] added logic for handling of availability zones with share groups and [2] for scheduling with share group capability to create consistent snapshots. Those two added two new DB fields for 'share_groups' DB model, but not to API response that requires microversion bump. So, add these fields to API and bump microversion. Following two new fields will be available with new microversion: - 'availability_zone_id' - 'consistent_snapshot_support' Also, add tempest tests to these API changes. [1] I000adeb53fe8435465cbedc3c539e6aaae6503c5 [2] I05553c308ae40c4ddc2c6469ff1c1a3da36a87da Partially-Implements BP manila-share-groups Change-Id: I343d0c6f3a5c7b58d88e95dba4af984fae738954
This commit is contained in:
@@ -100,13 +100,15 @@ REST_API_VERSION_HISTORY = """
|
|||||||
* 2.32 - Added mountable snapshots APIs.
|
* 2.32 - Added mountable snapshots APIs.
|
||||||
* 2.33 - Added 'created_at' and 'updated_at' to the response of
|
* 2.33 - Added 'created_at' and 'updated_at' to the response of
|
||||||
access_list API.
|
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 minimum and maximum versions of the API supported
|
||||||
# The default api version request is defined to be the
|
# The default api version request is defined to be the
|
||||||
# minimum version of the API supported.
|
# minimum version of the API supported.
|
||||||
_MIN_API_VERSION = "2.0"
|
_MIN_API_VERSION = "2.0"
|
||||||
_MAX_API_VERSION = "2.33"
|
_MAX_API_VERSION = "2.34"
|
||||||
DEFAULT_API_VERSION = _MIN_API_VERSION
|
DEFAULT_API_VERSION = _MIN_API_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
@@ -195,3 +195,8 @@ user documentation.
|
|||||||
2.33
|
2.33
|
||||||
----
|
----
|
||||||
Added created_at and updated_at in access_list API.
|
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.
|
||||||
|
@@ -20,6 +20,9 @@ class ShareGroupViewBuilder(common.ViewBuilder):
|
|||||||
"""Model a share group API response as a python dictionary."""
|
"""Model a share group API response as a python dictionary."""
|
||||||
|
|
||||||
_collection_name = 'share_groups'
|
_collection_name = 'share_groups'
|
||||||
|
_detail_version_modifiers = [
|
||||||
|
"add_consistent_snapshot_support_and_az_id_fields_to_sg",
|
||||||
|
]
|
||||||
|
|
||||||
def summary_list(self, request, share_groups):
|
def summary_list(self, request, share_groups):
|
||||||
"""Show a list of share groups without many details."""
|
"""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': [st['share_type_id'] for st in share_group.get(
|
||||||
'share_types')],
|
'share_types')],
|
||||||
'links': self._get_links(request, share_group['id']),
|
'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:
|
if context.is_admin:
|
||||||
share_group_dict['share_server_id'] = share_group.get(
|
share_group_dict['share_server_id'] = share_group.get(
|
||||||
'share_server_id')
|
'share_server_id')
|
||||||
return {'share_group': share_group_dict}
|
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):
|
def _list_view(self, func, request, shares):
|
||||||
"""Provide a view for a list of share groups."""
|
"""Provide a view for a list of share groups."""
|
||||||
share_group_list = [
|
share_group_list = [
|
||||||
|
@@ -53,7 +53,7 @@ class ShareGroupAPITest(test.TestCase):
|
|||||||
self.fake_share_type = {'id': six.text_type(uuidutils.generate_uuid())}
|
self.fake_share_type = {'id': six.text_type(uuidutils.generate_uuid())}
|
||||||
self.fake_share_group_type = {
|
self.fake_share_group_type = {
|
||||||
'id': six.text_type(uuidutils.generate_uuid())}
|
'id': six.text_type(uuidutils.generate_uuid())}
|
||||||
self.api_version = '2.31'
|
self.api_version = '2.34'
|
||||||
self.request = fakes.HTTPRequest.blank(
|
self.request = fakes.HTTPRequest.blank(
|
||||||
'/share-groups', version=self.api_version, experimental=True)
|
'/share-groups', version=self.api_version, experimental=True)
|
||||||
self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake')
|
self.flags(rpc_backend='manila.openstack.common.rpc.impl_fake')
|
||||||
@@ -94,7 +94,8 @@ class ShareGroupAPITest(test.TestCase):
|
|||||||
'name': None,
|
'name': None,
|
||||||
'description': None,
|
'description': None,
|
||||||
'host': None,
|
'host': None,
|
||||||
'availability_zone_id': None,
|
'availability_zone': None,
|
||||||
|
'consistent_snapshot_support': None,
|
||||||
'source_share_group_snapshot_id': None,
|
'source_share_group_snapshot_id': None,
|
||||||
'share_group_type_id': self.fake_share_group_type.get('id'),
|
'share_group_type_id': self.fake_share_group_type.get('id'),
|
||||||
'share_network_id': uuidutils.generate_uuid(),
|
'share_network_id': uuidutils.generate_uuid(),
|
||||||
@@ -112,10 +113,9 @@ class ShareGroupAPITest(test.TestCase):
|
|||||||
'name': share_group_db_dict['name'],
|
'name': share_group_db_dict['name'],
|
||||||
'description': share_group_db_dict['description'],
|
'description': share_group_db_dict['description'],
|
||||||
'host': share_group_db_dict['host'],
|
'host': share_group_db_dict['host'],
|
||||||
# NOTE(vponomaryov): uncomment following when API start returning
|
'availability_zone': share_group_db_dict['availability_zone'],
|
||||||
# availability zone value.
|
'consistent_snapshot_support': share_group_db_dict[
|
||||||
# 'availability_zone_id': share_group_db_dict[
|
'consistent_snapshot_support'],
|
||||||
# 'availability_zone_id'],
|
|
||||||
'source_share_group_snapshot_id': share_group_db_dict[
|
'source_share_group_snapshot_id': share_group_db_dict[
|
||||||
'source_share_group_snapshot_id'],
|
'source_share_group_snapshot_id'],
|
||||||
'share_group_type_id': share_group_db_dict['share_group_type_id'],
|
'share_group_type_id': share_group_db_dict['share_group_type_id'],
|
||||||
|
@@ -30,7 +30,7 @@ ShareGroup = [
|
|||||||
help="The minimum api microversion is configured to be the "
|
help="The minimum api microversion is configured to be the "
|
||||||
"value of the minimum microversion supported by Manila."),
|
"value of the minimum microversion supported by Manila."),
|
||||||
cfg.StrOpt("max_api_microversion",
|
cfg.StrOpt("max_api_microversion",
|
||||||
default="2.33",
|
default="2.34",
|
||||||
help="The maximum api microversion is configured to be the "
|
help="The maximum api microversion is configured to be the "
|
||||||
"value of the latest microversion supported by Manila."),
|
"value of the latest microversion supported by Manila."),
|
||||||
cfg.StrOpt("region",
|
cfg.StrOpt("region",
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import ddt
|
||||||
from tempest import config
|
from tempest import config
|
||||||
from tempest.lib import exceptions as lib_exc
|
from tempest.lib import exceptions as lib_exc
|
||||||
import testtools
|
import testtools
|
||||||
@@ -27,6 +28,7 @@ CONF = config.CONF
|
|||||||
@testtools.skipUnless(
|
@testtools.skipUnless(
|
||||||
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
|
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
|
||||||
@base.skip_if_microversion_lt(constants.MIN_SHARE_GROUP_MICROVERSION)
|
@base.skip_if_microversion_lt(constants.MIN_SHARE_GROUP_MICROVERSION)
|
||||||
|
@ddt.ddt
|
||||||
class ShareGroupsTest(base.BaseSharesTest):
|
class ShareGroupsTest(base.BaseSharesTest):
|
||||||
"""Covers share group functionality."""
|
"""Covers share group functionality."""
|
||||||
|
|
||||||
@@ -163,3 +165,58 @@ class ShareGroupsTest(base.BaseSharesTest):
|
|||||||
share_group['share_network_id'],
|
share_group['share_network_id'],
|
||||||
new_share_group['share_network_id'],
|
new_share_group['share_network_id'],
|
||||||
msg)
|
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'])
|
||||||
|
@@ -237,3 +237,37 @@ class ShareGroupsNegativeTest(base.BaseSharesTest):
|
|||||||
version=constants.MIN_SHARE_GROUP_MICROVERSION,
|
version=constants.MIN_SHARE_GROUP_MICROVERSION,
|
||||||
)
|
)
|
||||||
self.assertEqual(0, len(shares), 'Incorrect number of shares returned')
|
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')
|
||||||
|
@@ -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.
|
Reference in New Issue
Block a user