Add 'snapshot_support' attr to share details

Recently was introduced feature where snapshots become optional.

Share started have new attr "snapshot_support". But it is absent in
share payload and, hence, can not be used outside of Manila.

Also, fix lost import of translation function for related snapshot API.

Change-Id: Iddb0cf1e046b9d480a22e79b33c8674a2405362e
Closes-Bug: #1491345
Closes-Bug: #1491346
This commit is contained in:
Valeriy Ponomaryov 2015-09-08 12:59:41 +03:00
parent 6a00600ac0
commit 3ea5752570
7 changed files with 95 additions and 29 deletions

View File

@ -24,7 +24,7 @@ from manila.api import common
from manila.api.openstack import wsgi
from manila.api.views import share_snapshots as snapshot_views
from manila import exception
from manila.i18n import _LI
from manila.i18n import _, _LI
from manila import share
LOG = log.getLogger(__name__)

View File

@ -212,10 +212,7 @@ class ShareController(wsgi.Controller):
@wsgi.Controller.api_version("1.0", "2.3") # noqa
def create(self, req, body): # pylint: disable=E0102
# Remove consistency group attributes
share = body.get('share', {})
if 'consistency_group_id' in share:
del body['share']['consistency_group_id']
body.get('share', {}).pop('consistency_group_id', None)
share = self._create(req, body)
return share

View File

@ -21,6 +21,7 @@ class ViewBuilder(common.ViewBuilder):
_collection_name = 'shares'
_detail_version_modifiers = [
"add_snapshot_support_field",
"add_consistency_group_fields",
"add_task_state_field",
"modify_share_type_field",
@ -88,6 +89,10 @@ class ViewBuilder(common.ViewBuilder):
share_dict['share_server_id'] = share.get('share_server_id')
return {'share': share_dict}
@common.ViewBuilder.versioned_method("2.2")
def add_snapshot_support_field(self, share_dict, share):
share_dict['snapshot_support'] = share.get('snapshot_support')
@common.ViewBuilder.versioned_method("2.4")
def add_consistency_group_fields(self, share_dict, share):
share_dict['consistency_group_id'] = share.get(

View File

@ -16,6 +16,7 @@
import copy
import datetime
import ddt
import mock
from oslo_config import cfg
import webob
@ -46,6 +47,7 @@ def app():
return mapper
@ddt.ddt
class ShareApiTest(test.TestCase):
"""Share Api Test."""
def setUp(self):
@ -103,6 +105,7 @@ class ShareApiTest(test.TestCase):
'status': 'fakestatus',
'share_type': '1',
'volume_type': '1',
'snapshot_support': True,
'is_public': False,
'links': [
{
@ -127,25 +130,38 @@ class ShareApiTest(test.TestCase):
share['share_server_id'] = 'fake_share_server_id'
return {'share': share}
def test_share_create(self):
@ddt.data("1.0", "2.0", "2.1")
def test_share_create_original(self, microversion):
self.mock_object(share_api.API, 'create', self.create_mock)
body = {"share": copy.deepcopy(self.share)}
req = fakes.HTTPRequest.blank('/shares')
req = fakes.HTTPRequest.blank('/shares', version=microversion)
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(self.share)
expected['share'].pop('snapshot_support')
self.assertEqual(expected, res_dict)
@ddt.data("2.2", "2.3")
def test_share_create_with_snapshot_support_without_cg(self, microversion):
self.mock_object(share_api.API, 'create', self.create_mock)
body = {"share": copy.deepcopy(self.share)}
req = fakes.HTTPRequest.blank('/shares', version=microversion)
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(self.share)
self.assertEqual(expected, res_dict)
def test_share_create_with_consistency_group(self):
@ddt.data("2.4", "2.5")
def test_share_create_with_consistency_group(self, microversion):
self.mock_object(share_api.API, 'create', self.create_mock)
body = {"share": copy.deepcopy(self.share)}
req = fakes.HTTPRequest.blank('/shares', version="2.4")
req = fakes.HTTPRequest.blank('/shares', version=microversion)
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(self.share)
expected['share']['consistency_group_id'] = None
expected['share']['source_cgsnapshot_member_id'] = None
self.assertEqual(expected, res_dict)
@ -161,6 +177,7 @@ class ShareApiTest(test.TestCase):
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(self.share)
expected['share'].pop('snapshot_support')
share_types.get_share_type_by_name.assert_called_once_with(
utils.IsAMatcher(context.RequestContext), self.vt['name'])
self.assertEqual(expected, res_dict)
@ -202,6 +219,7 @@ class ShareApiTest(test.TestCase):
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(shr)
expected['share'].pop('snapshot_support')
self.assertEqual(expected, res_dict)
self.assertEqual(create_mock.call_args[1]['share_network_id'],
"fakenetid")
@ -285,6 +303,7 @@ class ShareApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/shares')
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(shr)
expected['share'].pop('snapshot_support')
self.assertEqual(expected, res_dict)
def test_share_create_from_snapshot_without_share_net_parent_exists(self):
@ -318,6 +337,7 @@ class ShareApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/shares')
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(shr)
expected['share'].pop('snapshot_support')
self.assertEqual(expected, res_dict)
self.assertEqual(create_mock.call_args[1]['share_network_id'],
parent_share_net)
@ -353,6 +373,7 @@ class ShareApiTest(test.TestCase):
req = fakes.HTTPRequest.blank('/shares')
res_dict = self.controller.create(req, body)
expected = self._get_expected_share_detailed_response(shr)
expected['share'].pop('snapshot_support')
self.assertEqual(res_dict, expected)
self.assertEqual(create_mock.call_args[1]['share_network_id'],
parent_share_net)
@ -412,16 +433,21 @@ class ShareApiTest(test.TestCase):
def test_share_show(self):
req = fakes.HTTPRequest.blank('/shares/1')
res_dict = self.controller.show(req, '1')
expected = self._get_expected_share_detailed_response()
expected['share'].pop('snapshot_support')
res_dict = self.controller.show(req, '1')
self.assertEqual(expected, res_dict)
def test_share_show_with_consistency_group(self):
req = fakes.HTTPRequest.blank('/shares/1', version='2.4')
res_dict = self.controller.show(req, '1')
expected = self._get_expected_share_detailed_response()
expected['share']['consistency_group_id'] = None
expected['share']['source_cgsnapshot_member_id'] = None
res_dict = self.controller.show(req, '1')
self.assertEqual(expected, res_dict)
def test_share_show_with_share_type_name(self):
@ -435,8 +461,11 @@ class ShareApiTest(test.TestCase):
def test_share_show_admin(self):
req = fakes.HTTPRequest.blank('/shares/1', use_admin_context=True)
res_dict = self.controller.show(req, '1')
expected = self._get_expected_share_detailed_response(admin=True)
expected['share'].pop('snapshot_support')
res_dict = self.controller.show(req, '1')
self.assertEqual(expected, res_dict)
def test_share_show_no_share(self):
@ -706,6 +735,7 @@ class ShareApiTest(test.TestCase):
'host': 'fakehost',
'id': '1',
'snapshot_id': '2',
'snapshot_support': True,
'share_network_id': None,
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
'size': 1,
@ -738,6 +768,7 @@ class ShareApiTest(test.TestCase):
env = {'QUERY_STRING': 'name=Share+Test+Name'}
req = fakes.HTTPRequest.blank('/shares/detail', environ=env)
expected = self._list_detail_common_expected()
expected['shares'][0].pop('snapshot_support')
self._list_detail_test_common(req, expected)
def test_share_list_detail_with_consistency_group(self):

View File

@ -288,7 +288,7 @@ class BaseSharesTest(test.BaseTestCase):
share_network_id=None, share_type_id=None,
consistency_group_id=None, client=None,
cleanup_in_class=True, is_public=False, **kwargs):
client = client or cls.shares_client
client = client or cls.shares_v2_client
description = description or "Tempest's share"
share_network_id = share_network_id or client.share_network_id or None
metadata = metadata or {}
@ -358,7 +358,7 @@ class BaseSharesTest(test.BaseTestCase):
"Expected only 'args' and 'kwargs' keys. "
"Provided %s" % list(d))
d["kwargs"]["client"] = d["kwargs"].get(
"client", cls.shares_client)
"client", cls.shares_v2_client)
d["share"] = cls._create_share(*d["args"], **d["kwargs"])
d["cnt"] = 0
d["available"] = False

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
from tempest import config # noqa
from tempest import test # noqa
from tempest_lib import exceptions as lib_exc # noqa
@ -35,17 +36,19 @@ class SharesNFSTest(base.BaseSharesTest):
raise cls.skipException(message)
cls.share = cls.create_share(cls.protocol)
@test.attr(type=["gate", ])
def test_create_delete_share(self):
def _create_delete_share(self, version):
# create share
share = self.create_share(self.protocol)
share = self.create_share(
self.protocol, version=six.text_type(version))
detailed_elements = {'name', 'id', 'availability_zone',
'description', 'export_location', 'project_id',
'host', 'created_at', 'share_proto', 'metadata',
'size', 'snapshot_id', 'share_network_id',
'status', 'share_type', 'volume_type', 'links',
'is_public'}
if version > 2.2:
detailed_elements.add('snapshot_support')
self.assertTrue(detailed_elements.issubset(share.keys()),
'At least one expected element missing from share '
'response. Expected %(expected)s, got %(actual)s.' % {
@ -60,6 +63,14 @@ class SharesNFSTest(base.BaseSharesTest):
self.shares_client.get_share,
share['id'])
@test.attr(type=["gate", ])
def test_create_delete_share_without_snapshot_support_feature(self):
self._create_delete_share(2.1)
@test.attr(type=["gate", ])
def test_create_delete_share_with_snapshot_support_feature(self):
self._create_delete_share(2.2)
@test.attr(type=["gate", ])
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
from tempest import config # noqa
from tempest import test # noqa
from tempest_lib.common.utils import data_utils # noqa
@ -71,33 +72,44 @@ class SharesActionsTest(base.BaseSharesTest):
snapshot_id=cls.snap['id'],
))
@test.attr(type=["gate", ])
def test_get_share(self):
def _get_share(self, version):
# get share
share = self.shares_client.get_share(self.shares[0]['id'])
share = self.shares_v2_client.get_share(
self.shares[0]['id'], version=six.text_type(version))
# verify keys
expected_keys = ["status", "description", "links", "availability_zone",
"created_at", "export_location", "share_proto",
"name", "snapshot_id", "id", "size"]
actual_keys = share.keys()
if version > 2.1:
expected_keys.append("snapshot_support")
actual_keys = list(share.keys())
[self.assertIn(key, actual_keys) for key in expected_keys]
# verify values
msg = "Expected name: '%s', actual name: '%s'" % (self.share_name,
share["name"])
self.assertEqual(self.share_name, str(share["name"]), msg)
self.assertEqual(self.share_name, six.text_type(share["name"]), msg)
msg = "Expected description: '%s', "\
"actual description: '%s'" % (self.share_desc,
share["description"])
self.assertEqual(self.share_desc, str(share["description"]), msg)
self.assertEqual(
self.share_desc, six.text_type(share["description"]), msg)
msg = "Expected size: '%s', actual size: '%s'" % (self.share_size,
share["size"])
self.assertEqual(self.share_size, int(share["size"]), msg)
@test.attr(type=["gate", ])
def test_get_share_no_snapshot_support_key(self):
self._get_share(2.1)
@test.attr(type=["gate", ])
def test_get_share_with_snapshot_support_key(self):
self._get_share(2.2)
@test.attr(type=["gate", ])
def test_list_shares(self):
@ -114,11 +126,11 @@ class SharesActionsTest(base.BaseSharesTest):
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
@test.attr(type=["gate", ])
def test_list_shares_with_detail(self):
def _list_shares_with_detail(self, version):
# list shares
shares = self.shares_client.list_shares_with_detail()
shares = self.shares_v2_client.list_shares_with_detail(
version=six.text_type(version))
# verify keys
keys = [
@ -126,6 +138,8 @@ class SharesActionsTest(base.BaseSharesTest):
"created_at", "export_location", "share_proto", "host",
"name", "snapshot_id", "id", "size", "project_id",
]
if version > 2.1:
keys.append("snapshot_support")
[self.assertIn(key, sh.keys()) for sh in shares for key in keys]
# our shares in list and have no duplicates
@ -134,6 +148,14 @@ class SharesActionsTest(base.BaseSharesTest):
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
@test.attr(type=["gate", ])
def test_list_shares_with_detail_without_snapshot_support_key(self):
self._list_shares_with_detail(2.1)
@test.attr(type=["gate", ])
def test_list_shares_with_detail_and_snapshot_support_key(self):
self._list_shares_with_detail(2.2)
@test.attr(type=["gate", ])
def test_list_shares_with_detail_filter_by_metadata(self):
filters = {'metadata': self.metadata}