From 38434795445270efdbec9c0471e36498fc1045ca Mon Sep 17 00:00:00 2001
From: wangxiyuan <wangxiyuan@huawei.com>
Date: Fri, 9 Dec 2016 15:40:38 +0800
Subject: [PATCH] Don't drop the volume type's extra spec at DB layer

Now the volume type's extra spec will be always dropped at
DB layer if the request is non admin. But this behavior is
controled by policy. We should return the extra specs to API and
let the policy check to decide whether drop it or not.

Change-Id: I1130a53a02da7aa4b8eb0587186331166d2b9bc1
Closes-bug: #1648717
---
 cinder/db/sqlalchemy/api.py            | 11 +++++-----
 cinder/tests/unit/api/v2/test_types.py | 30 ++++++++++++++++++++++++++
 cinder/tests/unit/test_volume_types.py |  6 +++---
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py
index dde7d0e99e7..846584af8b6 100644
--- a/cinder/db/sqlalchemy/api.py
+++ b/cinder/db/sqlalchemy/api.py
@@ -754,12 +754,11 @@ def _dict_with_extra_specs_if_authorized(context, inst_type_query):
     """
 
     inst_type_dict = dict(inst_type_query)
-    if not is_admin_context(context):
-        del(inst_type_dict['extra_specs'])
-    else:
-        extra_specs = {x['key']: x['value']
-                       for x in inst_type_query['extra_specs']}
-        inst_type_dict['extra_specs'] = extra_specs
+
+    extra_specs = {x['key']: x['value']
+                   for x in inst_type_query['extra_specs']}
+    inst_type_dict['extra_specs'] = extra_specs
+
     return inst_type_dict
 
 
diff --git a/cinder/tests/unit/api/v2/test_types.py b/cinder/tests/unit/api/v2/test_types.py
index 58aeb8b0c52..df50b835fae 100644
--- a/cinder/tests/unit/api/v2/test_types.py
+++ b/cinder/tests/unit/api/v2/test_types.py
@@ -397,6 +397,36 @@ class VolumeTypesApiTest(test.TestCase):
             )
             self.assertDictEqual(expected_volume_type, output['volume_type'])
 
+        with mock.patch.object(common,
+                               'validate_policy',
+                               side_effect=[False, False]):
+            view_builder = views_types.ViewBuilder()
+            now = timeutils.utcnow().isoformat()
+            raw_volume_type = dict(
+                name='new_type',
+                description='new_type_desc',
+                qos_specs_id='new_id',
+                is_public=True,
+                deleted=False,
+                created_at=now,
+                updated_at=now,
+                extra_specs={},
+                deleted_at=None,
+                id=42,
+            )
+
+            request = fakes.HTTPRequest.blank("/v2")
+            output = view_builder.show(request, raw_volume_type)
+
+            self.assertIn('volume_type', output)
+            expected_volume_type = dict(
+                name='new_type',
+                description='new_type_desc',
+                is_public=True,
+                id=42,
+            )
+            self.assertDictEqual(expected_volume_type, output['volume_type'])
+
     def test_view_builder_show_pass_all_policy(self):
         with mock.patch.object(common,
                                'validate_policy',
diff --git a/cinder/tests/unit/test_volume_types.py b/cinder/tests/unit/test_volume_types.py
index 34e022c1f7b..d51a6aaf668 100644
--- a/cinder/tests/unit/test_volume_types.py
+++ b/cinder/tests/unit/test_volume_types.py
@@ -496,15 +496,15 @@ class VolumeTypeTestCase(test.TestCase):
         self.assertFalse(volume_types.is_public_volume_type(self.ctxt,
                                                             volume_type_id))
 
-    def test_ensure_no_extra_specs_for_non_admin(self):
-        # non-admin users shouldn't get extra-specs back in type-get/list etc
+    def test_ensure__extra_specs_for_non_admin(self):
+        # non-admin users get extra-specs back in type-get/list etc at DB layer
         ctxt = context.RequestContext('average-joe',
                                       'd802f078-0af1-4e6b-8c02-7fac8d4339aa',
                                       auth_token='token',
                                       is_admin=False)
         volume_types.create(self.ctxt, "type-test", is_public=False)
         vtype = volume_types.get_volume_type_by_name(ctxt, 'type-test')
-        self.assertIsNone(vtype.get('extra_specs', None))
+        self.assertIsNotNone(vtype.get('extra_specs', None))
 
     def test_ensure_extra_specs_for_admin(self):
         # admin users should get extra-specs back in type-get/list etc