From b2e92b85b5ea2fc4058d6c0f6e9e3fddc2a9036e Mon Sep 17 00:00:00 2001 From: Nate Potter Date: Tue, 13 Oct 2015 19:53:23 +0000 Subject: [PATCH] Add qos_specs_id to volume type show Adding qos_specs_id to the output of volume type show to make getting the qos specs for a volume type more convenient. However, this variable will only be visible when type show is called with the admin role. APIImpact Change-Id: Id8a2333267c9a51b36c6adfbd142dcc4fbe4f090 Closes-Bug: #1438488 --- cinder/api/v2/types.py | 3 +- cinder/api/v2/views/types.py | 38 ++++++++++++++ cinder/tests/unit/api/v2/test_types.py | 72 +++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 cinder/api/v2/views/types.py diff --git a/cinder/api/v2/types.py b/cinder/api/v2/types.py index a1dce7342..4109ec541 100644 --- a/cinder/api/v2/types.py +++ b/cinder/api/v2/types.py @@ -19,7 +19,7 @@ from oslo_utils import strutils from webob import exc from cinder.api.openstack import wsgi -from cinder.api.views import types as views_types +from cinder.api.v2.views import types as views_types from cinder.api import xmlutil from cinder import exception from cinder.i18n import _ @@ -31,6 +31,7 @@ def make_voltype(elem): elem.set('id') elem.set('name') elem.set('description') + elem.set('qos_specs_id') extra_specs = xmlutil.make_flat_dict('extra_specs', selector='extra_specs') elem.append(extra_specs) diff --git a/cinder/api/v2/views/types.py b/cinder/api/v2/views/types.py new file mode 100644 index 000000000..af8a04954 --- /dev/null +++ b/cinder/api/v2/views/types.py @@ -0,0 +1,38 @@ +# Copyright 2012 Red Hat, Inc. +# Copyright 2015 Intel Corporation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# 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 cinder.api import common + + +class ViewBuilder(common.ViewBuilder): + + def show(self, request, volume_type, brief=False): + """Trim away extraneous volume type attributes.""" + context = request.environ['cinder.context'] + trimmed = dict(id=volume_type.get('id'), + name=volume_type.get('name'), + is_public=volume_type.get('is_public'), + extra_specs=volume_type.get('extra_specs'), + description=volume_type.get('description')) + if context.is_admin: + trimmed['qos_specs_id'] = volume_type.get('qos_specs_id') + return trimmed if brief else dict(volume_type=trimmed) + + def index(self, request, volume_types): + """Index over trimmed volume types.""" + volume_types_list = [self.show(request, volume_type, True) + for volume_type in volume_types] + return dict(volume_types=volume_types_list) diff --git a/cinder/tests/unit/api/v2/test_types.py b/cinder/tests/unit/api/v2/test_types.py index f819cbdcd..e9287d5ba 100644 --- a/cinder/tests/unit/api/v2/test_types.py +++ b/cinder/tests/unit/api/v2/test_types.py @@ -21,7 +21,7 @@ import six import webob from cinder.api.v2 import types -from cinder.api.views import types as views_types +from cinder.api.v2.views import types as views_types from cinder import exception from cinder import test from cinder.tests.unit.api import fakes @@ -153,6 +153,7 @@ class VolumeTypesApiTest(test.TestCase): raw_volume_type = dict( name='new_type', description='new_type_desc', + qos_specs_id='new_id', is_public=True, deleted=False, created_at=now, @@ -175,6 +176,37 @@ class VolumeTypesApiTest(test.TestCase): ) self.assertDictMatch(output['volume_type'], expected_volume_type) + def test_view_builder_show_admin(self): + 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", use_admin_context=True) + output = view_builder.show(request, raw_volume_type) + + self.assertIn('volume_type', output) + expected_volume_type = dict( + name='new_type', + description='new_type_desc', + qos_specs_id='new_id', + is_public=True, + extra_specs={}, + id=42, + ) + self.assertDictMatch(expected_volume_type, output['volume_type']) + def test_view_builder_list(self): view_builder = views_types.ViewBuilder() @@ -185,6 +217,7 @@ class VolumeTypesApiTest(test.TestCase): dict( name='new_type', description='new_type_desc', + qos_specs_id='new_id', is_public=True, deleted=False, created_at=now, @@ -210,6 +243,43 @@ class VolumeTypesApiTest(test.TestCase): self.assertDictMatch(output['volume_types'][i], expected_volume_type) + def test_view_builder_list_admin(self): + view_builder = views_types.ViewBuilder() + + now = timeutils.utcnow().isoformat() + raw_volume_types = [] + for i in range(0, 10): + raw_volume_types.append( + 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 + i + ) + ) + + request = fakes.HTTPRequest.blank("/v2", use_admin_context=True) + output = view_builder.index(request, raw_volume_types) + + self.assertIn('volume_types', output) + for i in range(0, 10): + expected_volume_type = dict( + name='new_type', + description='new_type_desc', + qos_specs_id='new_id', + is_public=True, + extra_specs={}, + id=42 + i + ) + self.assertDictMatch(expected_volume_type, + output['volume_types'][i]) + class VolumeTypesSerializerTest(test.TestCase): def _verify_volume_type(self, vtype, tree): -- 2.45.2