Merge "Retrieve is_default value to fix empty display in CLI"

This commit is contained in:
Zuul 2018-07-24 19:31:55 +00:00 committed by Gerrit Code Review
commit 3abfbef591
17 changed files with 287 additions and 5 deletions

View File

@ -1611,6 +1611,24 @@ is_admin_only:
in: body
required: true
type: boolean
is_default_type:
description: |
Defines the share type created is default or not. If the returning
value is true, then it is the default share type, otherwise, it is
not default.
in: body
required: true
type: boolean
min_version: 2.46
is_group_type_default:
description: |
Defines the share group type created is default or not. If the
returning value is true, then it is the default share group type,
otherwise, it is not default.
in: body
required: true
type: boolean
min_version: 2.46
is_public:
description: |
(Since API v2.8) The level of visibility for the

View File

@ -4,6 +4,7 @@
"group_specs": {},
"share_types": ["ecd11f4c-d811-4471-b656-c755c77e02ba"],
"id": "89861c2a-10bf-4013-bdd4-3d020466aee4",
"name": "test_group_type"
"name": "test_group_type",
"is_default": false
}
}

View File

@ -4,6 +4,7 @@
"group_specs": {},
"share_types": ["ecd11f4c-d811-4471-b656-c755c77e02ba"],
"id": "89861c2a-10bf-4013-bdd4-3d020466aee4",
"name": "test_group_type"
"name": "test_group_type",
"is_default": true
}
}

View File

@ -5,7 +5,8 @@
"group_specs": {},
"share_types": ["ecd11f4c-d811-4471-b656-c755c77e02ba"],
"id": "89861c2a-10bf-4013-bdd4-3d020466aee4",
"name": "test_group_type"
"name": "test_group_type",
"is_default": false
}
]
}

View File

@ -14,6 +14,7 @@
},
"id": "7fa1342b-de9d-4d89-bdc8-af67795c0e52",
"name": "testing",
"is_default": false,
"description": "share type description"
},
"volume_type": {
@ -31,6 +32,7 @@
},
"id": "7fa1342b-de9d-4d89-bdc8-af67795c0e52",
"name": "testing",
"is_default": false,
"description": "share type description"
}
}

View File

@ -9,6 +9,7 @@
},
"id": "2780fc88-526b-464a-a72c-ecb83f0e3929",
"name": "default-share-type",
"is_default": true,
"description": "manila share type"
},
"volume_type": {
@ -21,6 +22,7 @@
},
"id": "2780fc88-526b-464a-a72c-ecb83f0e3929",
"name": "default-share-type",
"is_default": true,
"description": "manila share type"
}
}

View File

@ -9,6 +9,7 @@
},
"id": "420e6a31-3f3d-4ed7-9d11-59450372182a",
"name": "default",
"is_default": true,
"description": "share type description"
},
"volume_type": {
@ -21,6 +22,7 @@
},
"id": "420e6a31-3f3d-4ed7-9d11-59450372182a",
"name": "default",
"is_default": true,
"description": "share type description"
}
}

View File

@ -10,6 +10,7 @@
},
"id": "420e6a31-3f3d-4ed7-9d11-59450372182a",
"name": "default",
"is_default": true,
"description": "share type description"
},
{
@ -27,6 +28,7 @@
},
"id": "7fa1342b-de9d-4d89-bdc8-af67795c0e52",
"name": "testing",
"is_default": false,
"description": "share type description"
}
],
@ -41,6 +43,7 @@
},
"id": "420e6a31-3f3d-4ed7-9d11-59450372182a",
"name": "default",
"is_default": true,
"description": "share type description"
},
{
@ -58,6 +61,7 @@
},
"id": "7fa1342b-de9d-4d89-bdc8-af67795c0e52",
"name": "testing",
"is_default": false,
"description": "share type description"
}
]

View File

@ -65,6 +65,7 @@ Response parameters
- share_types: share_types_1
- name: share_group_type_name
- group_specs: group_specs_required
- is_default: is_group_type_default
Response example
----------------
@ -111,6 +112,7 @@ Response parameters
- share_types: share_types_1
- name: share_group_type_name
- group_specs: group_specs_required
- is_default: is_group_type_default
Response example
----------------
@ -211,6 +213,7 @@ Response parameters
- name: share_group_type_name
- share_types: share_types_1
- is_public: share_group_type_is_public
- is_default: is_group_type_default
Response example
----------------

View File

@ -124,6 +124,7 @@ Response parameters
- share_type_access:is_public: share_type_access:is_public
- create_share_from_snapshot_support: create_share_from_snapshot_support
- description: share_type_description
- is_default: is_default_type
Response example
----------------
@ -173,6 +174,7 @@ Response parameters
- share_type_access:is_public: share_type_access:is_public
- name: share_type_name
- description: share_type_description
- is_default: is_default_type
Response example
----------------
@ -227,6 +229,7 @@ Response Parameters
- share_type_access:is_public: share_type_access:is_public
- name: share_type_name
- description: share_type_description
- is_default: is_default_type
Response Example
----------------
@ -348,6 +351,7 @@ Response parameters
- revert_to_snapshot_support: revert_to_snapshot_support
- create_share_from_snapshot_support: create_share_from_snapshot_support
- description: share_type_description
- is_default: is_default_type
Response example
----------------

View File

@ -119,13 +119,15 @@ REST_API_VERSION_HISTORY = """
* 2.45 - Added access metadata for share access and also introduced
the GET /share-access-rules API. The prior API to retrieve
access rules will not work with API version >=2.45.
* 2.46 - Added 'is_default' field to 'share_type' and 'share_group_type'
objects.
"""
# 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.45"
_MAX_API_VERSION = "2.46"
DEFAULT_API_VERSION = _MIN_API_VERSION

View File

@ -248,3 +248,8 @@ user documentation.
Added access metadata for share access and also introduced the
GET /share-access-rules API. The prior API to retrieve access
rules will not work with API version >=2.45.
2.46
----
Added 'is_default' field to 'share_type' and 'share_group_type'
objects.

View File

@ -9,13 +9,20 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from manila.api import common
CONF = cfg.CONF
class ShareGroupTypeViewBuilder(common.ViewBuilder):
_collection_name = 'share_group_types'
_detail_version_modifiers = [
"add_is_default_attr",
]
def show(self, request, share_group_type, brief=False):
"""Trim away extraneous share group type attributes."""
group_specs = share_group_type.get('group_specs', {})
@ -37,3 +44,15 @@ class ShareGroupTypeViewBuilder(common.ViewBuilder):
for share_group_type in share_group_types
]
return {"share_group_types": share_group_types_list}
@common.ViewBuilder.versioned_method("2.46")
def add_is_default_attr(self, context,
share_group_type_dict,
share_group_type):
is_default = False
type_name = share_group_type.get('name')
default_name = CONF.default_share_group_type
if default_name is not None:
is_default = default_name == type_name
share_group_type_dict['is_default'] = is_default

View File

@ -13,10 +13,14 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from manila.api import common
from manila.common import constants
from manila.share import share_types
CONF = cfg.CONF
class ViewBuilder(common.ViewBuilder):
@ -27,6 +31,7 @@ class ViewBuilder(common.ViewBuilder):
"add_is_public_attr_extension_like",
"add_inferred_optional_extra_specs",
"add_description_attr",
"add_is_default_attr"
]
def show(self, request, share_type, brief=False):
@ -103,3 +108,13 @@ class ViewBuilder(common.ViewBuilder):
@common.ViewBuilder.versioned_method("2.41")
def add_description_attr(self, context, share_type_dict, share_type):
share_type_dict['description'] = share_type.get('description')
@common.ViewBuilder.versioned_method("2.46")
def add_is_default_attr(self, context, share_type_dict, share_type):
is_default = False
type_name = share_type.get('name')
default_name = CONF.default_share_type
if default_name is not None:
is_default = default_name == type_name
share_type_dict['is_default'] = is_default

View File

@ -15,6 +15,7 @@ import datetime
import ddt
import mock
from oslo_config import cfg
import webob
from manila.api.v2 import share_group_types as types
@ -24,6 +25,8 @@ from manila.share_group import share_group_types
from manila import test
from manila.tests.api import fakes
CONF = cfg.CONF
PROJ1_UUID = '11111111-1111-1111-1111-111111111111'
PROJ2_UUID = '22222222-2222-2222-2222-222222222222'
PROJ3_UUID = '33333333-3333-3333-3333-333333333333'
@ -53,6 +56,18 @@ GROUP_TYPE_2 = {
'share_types': [{'share_type_id': SHARE_TYPE_ID}],
}
GROUP_TYPE_3 = {
'id': '61fdcbed-db27-4cc0-8938-8b4f74c2ae59',
'name': u'group type 3',
'deleted': False,
'created_at': datetime.datetime(2012, 1, 1, 1, 1, 1, 1),
'updated_at': None,
'deleted_at': None,
'is_public': True,
'group_specs': {},
'share_types': [],
}
def fake_request(url, admin=False, experimental=True, version='2.31',
**kwargs):
@ -430,6 +445,98 @@ class ShareGroupTypesAPITest(test.TestCase):
webob.exc.HTTPNotFound,
self.controller._create, req, fake_body)
@ddt.data(('2.45', True), ('2.45', False),
('2.46', True), ('2.46', False))
@ddt.unpack
def test_share_group_types_create_with_is_default_key(self,
version,
admin):
# is_default is false
fake_type = copy.deepcopy(GROUP_TYPE_1)
fake_type['share_types'] = [{'share_type_id': SHARE_TYPE_ID}]
self.mock_object(share_group_types, 'create')
self.mock_object(
share_group_types, 'get_by_name',
mock.Mock(return_value=fake_type))
req = fake_request('/v2/fake/share-group-types',
version=version,
admin=admin)
fake_body = {'share_group_type': {
'name': GROUP_TYPE_1['name'],
'share_types': [SHARE_TYPE_ID],
}}
res_dict = self.controller._create(req, fake_body)
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res_dict['share_group_type'])
self.assertIs(False, res_dict['share_group_type']['is_default'])
else:
self.assertNotIn('is_default', res_dict['share_group_type'])
# is_default is true
default_type_name = 'group type 3'
CONF.set_default('default_share_group_type', default_type_name)
fake_type = copy.deepcopy(GROUP_TYPE_3)
fake_type['share_types'] = [{'share_type_id': SHARE_TYPE_ID}]
self.mock_object(share_group_types, 'create')
self.mock_object(
share_group_types, 'get_by_name',
mock.Mock(return_value=fake_type))
req = fake_request('/v2/fake/share-group-types',
version=version,
admin=admin)
fake_body = {'share_group_type': {
'name': GROUP_TYPE_3['name'],
'share_types': [SHARE_TYPE_ID],
}}
res_dict = self.controller._create(req, fake_body)
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res_dict['share_group_type'])
self.assertIs(True, res_dict['share_group_type']['is_default'])
else:
self.assertNotIn('is_default', res_dict['share_group_type'])
@ddt.data(('2.45', True), ('2.45', False),
('2.46', True), ('2.46', False))
@ddt.unpack
def test_share_group_types_list_with_is_default_key(self, version, admin):
fake_types = {
GROUP_TYPE_1['name']: GROUP_TYPE_1,
GROUP_TYPE_2['name']: GROUP_TYPE_2,
}
self.mock_object(
share_group_types, 'get_all',
mock.Mock(return_value=fake_types))
req = fake_request(
'/v2/fake/share-group-types?is_public=all',
version=version,
admin=admin)
res_dict = self.controller.index(req)
for res in res_dict['share_group_types']:
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res)
self.assertIs(False, res['is_default'])
else:
self.assertNotIn('is_default', res)
self.assertEqual(2, len(res_dict['share_group_types']))
@ddt.data(('2.45', True), ('2.45', False),
('2.46', True), ('2.46', False))
@ddt.unpack
def test_shares_group_types_show_with_is_default_key(self, version, admin):
self.mock_object(
share_group_types, 'get',
mock.Mock(return_value=GROUP_TYPE_2))
req = fake_request('/v2/fake/group-types/%s' % GROUP_TYPE_2['id'],
version=version,
admin=admin)
res_dict = self.controller.show(req, GROUP_TYPE_2['id'])
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res_dict['share_group_type'])
self.assertIs(False, res_dict['share_group_type']['is_default'])
else:
self.assertNotIn('is_default', res_dict['share_group_type'])
class ShareGroupTypeAccessTest(test.TestCase):

View File

@ -17,6 +17,7 @@ import datetime
import ddt
import mock
from oslo_config import cfg
from oslo_utils import timeutils
import webob
@ -32,6 +33,8 @@ from manila import test
from manila.tests.api import fakes
from manila.tests import fake_notifier
CONF = cfg.CONF
def stub_share_type(id):
specs = {
@ -61,6 +64,34 @@ def return_share_types_get_all_types(context, search_opts=None):
)
def stub_default_name():
return 'default_share_type'
def stub_default_share_type(id):
return dict(
id=id,
name=stub_default_name(),
description='description_%s' % str(id),
required_extra_specs={
constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS: "true",
}
)
def return_all_share_types(context, search_opts=None):
mock_value = dict(
share_type_1=stub_share_type(1),
share_type_2=stub_share_type(2),
share_type_3=stub_default_share_type(3)
)
return mock_value
def return_default_share_type(context, search_opts=None):
return stub_default_share_type(3)
def return_empty_share_types_get_all_types(context, search_opts=None):
return {}
@ -491,6 +522,65 @@ class ShareTypesAPITest(test.TestCase):
for d1, d2 in zip(expected, observed):
self.assertEqual(d1['id'], d2['id'])
@ddt.data(('2.45', True), ('2.45', False),
('2.46', True), ('2.46', False))
@ddt.unpack
def test_share_types_create_with_is_default_key(self, version, admin):
req = fakes.HTTPRequest.blank('/v2/fake/types',
version=version,
use_admin_context=admin)
body = make_create_body()
res_dict = self.controller.create(req, body)
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res_dict['share_type'])
self.assertIs(False, res_dict['share_type']['is_default'])
else:
self.assertNotIn('is_default', res_dict['share_type'])
@ddt.data(('2.45', True), ('2.45', False),
('2.46', True), ('2.46', False))
@ddt.unpack
def test_share_types_index_with_is_default_key(self, version, admin):
default_type_name = stub_default_name()
CONF.set_default("default_share_type", default_type_name)
self.mock_object(share_types, 'get_all_types',
return_all_share_types)
req = fakes.HTTPRequest.blank('/v2/fake/types',
version=version,
use_admin_context=admin)
res_dict = self.controller.index(req)
self.assertEqual(3, len(res_dict['share_types']))
for res in res_dict['share_types']:
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res)
expected = res['name'] == default_type_name
self.assertIs(res['is_default'], expected)
else:
self.assertNotIn('is_default', res)
@ddt.data(('2.45', True), ('2.45', False),
('2.46', True), ('2.46', False))
@ddt.unpack
def test_share_types_default_with_is_default_key(self, version, admin):
default_type_name = stub_default_name()
CONF.set_default("default_share_type", default_type_name)
self.mock_object(share_types, 'get_default_share_type',
return_default_share_type)
req = fakes.HTTPRequest.blank('/v2/fake/types/default_share_type',
version=version,
use_admin_context=admin)
res_dict = self.controller.default(req)
if self.is_microversion_ge(version, '2.46'):
self.assertIn('is_default', res_dict['share_type'])
self.assertIs(True, res_dict['share_type']['is_default'])
else:
self.assertNotIn('is_default', res_dict['share_type'])
def generate_type(type_id, is_public):
return {

View File

@ -0,0 +1,6 @@
---
features:
- The share type and share group type APIs in API version 2.46 return
field "is_default" which is set to 'true' if the share type or the
share group type is the default as configured by the administrator.