From aeed2a788608b7b93bcdd70826ff0a3102c15027 Mon Sep 17 00:00:00 2001 From: PranaliDeore Date: Wed, 29 Apr 2015 02:35:52 -0700 Subject: [PATCH] Validate name and description for volume type If you pass name parameter with long string of more than 255 characters to type-create and type-update api, then it returns 500 error code. Added a check in _create() and _update() methods of 'types_manage' extension to validate string limit and returned 400 if limit exceeds. Closes-Bug: 1450388 Change-Id: I68c607df90a3dfeae7a841a1dddee5416fa42d13 --- cinder/api/contrib/types_manage.py | 16 ++++ .../unit/api/contrib/test_types_manage.py | 73 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/cinder/api/contrib/types_manage.py b/cinder/api/contrib/types_manage.py index 434d4fa43..33a4978bd 100644 --- a/cinder/api/contrib/types_manage.py +++ b/cinder/api/contrib/types_manage.py @@ -25,6 +25,7 @@ from cinder.api.views import types as views_types from cinder import exception from cinder.i18n import _ from cinder import rpc +from cinder import utils from cinder.volume import volume_types @@ -66,6 +67,13 @@ class VolumeTypesManageController(wsgi.Controller): msg = _("Volume type name can not be empty.") raise webob.exc.HTTPBadRequest(explanation=msg) + utils.check_string_length(name, 'Type name', + min_length=1, max_length=255) + + if description is not None: + utils.check_string_length(description, 'Type description', + min_length=0, max_length=255) + try: volume_types.create(context, name, @@ -112,6 +120,14 @@ class VolumeTypesManageController(wsgi.Controller): msg = _("Specify either volume type name and/or description.") raise webob.exc.HTTPBadRequest(explanation=msg) + if name: + utils.check_string_length(name, 'Type name', + min_length=1, max_length=255) + + if description is not None: + utils.check_string_length(description, 'Type description', + min_length=0, max_length=255) + try: volume_types.update(context, id, name, description) # Get the updated diff --git a/cinder/tests/unit/api/contrib/test_types_manage.py b/cinder/tests/unit/api/contrib/test_types_manage.py index f20419d14..ba7b2a861 100644 --- a/cinder/tests/unit/api/contrib/test_types_manage.py +++ b/cinder/tests/unit/api/contrib/test_types_manage.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import mock import six import webob @@ -198,6 +199,44 @@ class VolumeTypesManageApiTest(test.TestCase): self._check_test_results(res_dict, { 'expected_name': 'vol_type_1', 'expected_desc': 'vol_type_desc_1'}) + @mock.patch('cinder.volume.volume_types.create') + @mock.patch('cinder.volume.volume_types.get_volume_type_by_name') + def test_create_with_description_of_zero_length( + self, mock_get_volume_type_by_name, mock_create_type): + mock_get_volume_type_by_name.return_value = \ + {'extra_specs': {"key1": "value1"}, + 'id': 1, + 'name': u'vol_type_1', + 'description': u''} + + type_description = "" + body = {"volume_type": {"name": "vol_type_1", + "description": type_description, + "extra_specs": {"key1": "value1"}}} + req = fakes.HTTPRequest.blank('/v2/fake/types') + + res_dict = self.controller._create(req, body) + + self._check_test_results(res_dict, { + 'expected_name': 'vol_type_1', 'expected_desc': ''}) + + def test_create_type_with_name_too_long(self): + type_name = 'a' * 256 + body = {"volume_type": {"name": type_name, + "extra_specs": {"key1": "value1"}}} + req = fakes.HTTPRequest.blank('/v2/fake/types') + self.assertRaises(exception.InvalidInput, + self.controller._create, req, body) + + def test_create_type_with_description_too_long(self): + type_description = 'a' * 256 + body = {"volume_type": {"name": "vol_type_1", + "description": type_description, + "extra_specs": {"key1": "value1"}}} + req = fakes.HTTPRequest.blank('/v2/fake/types') + self.assertRaises(exception.InvalidInput, + self.controller._create, req, body) + def test_create_duplicate_type_fail(self): self.stubs.Set(volume_types, 'create', return_volume_types_create_duplicate_type) @@ -245,6 +284,40 @@ class VolumeTypesManageApiTest(test.TestCase): {'expected_desc': 'vol_type_desc_1_1', 'expected_name': 'vol_type_1_1'}) + @mock.patch('cinder.volume.volume_types.update') + @mock.patch('cinder.volume.volume_types.get_volume_type') + def test_update_type_with_description_having_length_zero( + self, mock_get_volume_type, mock_type_update): + + mock_get_volume_type.return_value = \ + {'id': 1, 'name': u'vol_type_1', 'description': u''} + + type_description = "" + body = {"volume_type": {"description": type_description}} + req = fakes.HTTPRequest.blank('/v2/fake/types/1') + req.method = 'PUT' + resp = self.controller._update(req, '1', body) + self._check_test_results(resp, + {'expected_desc': '', + 'expected_name': 'vol_type_1'}) + + def test_update_type_with_name_too_long(self): + type_name = 'a' * 256 + body = {"volume_type": {"name": type_name, + "description": ""}} + req = fakes.HTTPRequest.blank('/v2/fake/types/1') + req.method = 'PUT' + self.assertRaises(exception.InvalidInput, + self.controller._update, req, '1', body) + + def test_update_type_with_description_too_long(self): + type_description = 'a' * 256 + body = {"volume_type": {"description": type_description}} + req = fakes.HTTPRequest.blank('/v2/fake/types/1') + req.method = 'PUT' + self.assertRaises(exception.InvalidInput, + self.controller._update, req, '1', body) + def test_update_non_exist(self): self.stubs.Set(volume_types, 'update', return_volume_types_update) -- 2.45.2