diff --git a/cinder/api/schemas/group_specs.py b/cinder/api/schemas/group_specs.py new file mode 100644 index 00000000000..2453c383e7e --- /dev/null +++ b/cinder/api/schemas/group_specs.py @@ -0,0 +1,43 @@ +# Copyright (C) 2017 NTT DATA +# 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. + +import copy + + +group_specs_with_no_spaces_key_and_value_null = { + 'type': 'object', + 'patternProperties': { + '^[a-zA-Z0-9-_:.]{1,255}$': { + 'type': ['string', 'null'], 'maxLength': 255 + } + }, + 'additionalProperties': False +} + +create = { + 'type': 'object', + 'properties': { + 'type': 'object', + 'group_specs': group_specs_with_no_spaces_key_and_value_null, + }, + 'required': ['group_specs'], + 'additionalProperties': False, +} + +update = copy.deepcopy(group_specs_with_no_spaces_key_and_value_null) +update.update({ + 'minProperties': 1, + 'maxProperties': 1 +}) diff --git a/cinder/api/v3/group_specs.py b/cinder/api/v3/group_specs.py index 0af077f055c..abeeeeb57ac 100644 --- a/cinder/api/v3/group_specs.py +++ b/cinder/api/v3/group_specs.py @@ -17,15 +17,15 @@ from six.moves import http_client import webob -from cinder.api import common from cinder.api import microversions as mv from cinder.api.openstack import wsgi +from cinder.api.schemas import group_specs +from cinder.api import validation from cinder import db from cinder import exception from cinder.i18n import _ from cinder.policies import group_types as policy from cinder import rpc -from cinder import utils from cinder.volume import group_types @@ -55,16 +55,13 @@ class GroupTypeSpecsController(wsgi.Controller): @wsgi.Controller.api_version(mv.GROUP_TYPE) @wsgi.response(http_client.ACCEPTED) - def create(self, req, group_type_id, body=None): + @validation.schema(group_specs.create) + def create(self, req, group_type_id, body): context = req.environ['cinder.context'] context.authorize(policy.SPEC_POLICY) - self.assert_valid_body(body, 'group_specs') self._check_type(context, group_type_id) specs = body['group_specs'] - self._check_key_names(specs.keys()) - utils.validate_dictionary_string_length(specs) - db.group_type_specs_update_or_create(context, group_type_id, specs) @@ -75,22 +72,15 @@ class GroupTypeSpecsController(wsgi.Controller): return body @wsgi.Controller.api_version(mv.GROUP_TYPE) - def update(self, req, group_type_id, id, body=None): + @validation.schema(group_specs.update) + def update(self, req, group_type_id, id, body): context = req.environ['cinder.context'] context.authorize(policy.SPEC_POLICY) - if not body: - expl = _('Request body empty') - raise webob.exc.HTTPBadRequest(explanation=expl) self._check_type(context, group_type_id) if id not in body: expl = _('Request body and URI mismatch') raise webob.exc.HTTPBadRequest(explanation=expl) - if len(body) > 1: - expl = _('Request body contains too many items') - raise webob.exc.HTTPBadRequest(explanation=expl) - self._check_key_names(body.keys()) - utils.validate_dictionary_string_length(body) db.group_type_specs_update_or_create(context, group_type_id, @@ -137,13 +127,6 @@ class GroupTypeSpecsController(wsgi.Controller): notifier_info) return webob.Response(status_int=http_client.ACCEPTED) - def _check_key_names(self, keys): - if not common.validate_key_names(keys): - expl = _('Key names can only contain alphanumeric characters, ' - 'underscores, periods, colons and hyphens.') - - raise webob.exc.HTTPBadRequest(explanation=expl) - def create_resource(): return wsgi.Resource(GroupTypeSpecsController()) diff --git a/cinder/tests/unit/api/v3/test_group_specs.py b/cinder/tests/unit/api/v3/test_group_specs.py index 6ab66a09a59..87247ed59bb 100644 --- a/cinder/tests/unit/api/v3/test_group_specs.py +++ b/cinder/tests/unit/api/v3/test_group_specs.py @@ -18,6 +18,7 @@ import webob from cinder import context from cinder import db +from cinder import exception from cinder import rpc from cinder import test @@ -90,7 +91,8 @@ class GroupSpecsTestCase(test.TestCase): fake.PROJECT_ID, use_admin_context=True, version=mv.GROUP_TYPE) - self.controller.create(req, fake.GROUP_ID, create_fake_group_specs) + self.controller.create(req, fake.GROUP_ID, + body=create_fake_group_specs) self.assertTrue(mock_rpc_notifier.called) @mock.patch.object(rpc, 'get_notifier') @@ -111,7 +113,7 @@ class GroupSpecsTestCase(test.TestCase): self.controller.update(req, fake.GROUP_TYPE_ID, 'id', - update_fake_group_specs) + body=update_fake_group_specs) self.assertTrue(mock_rpc_notifier.called) @mock.patch.object(db, 'group_type_specs_get', @@ -155,7 +157,7 @@ class GroupSpecsTestCase(test.TestCase): self.controller.create, req, fake.GROUP_ID, - create_fake_group_specs) + body=create_fake_group_specs) @mock.patch.object(rpc, 'get_notifier') @mock.patch.object(db, 'group_type_get', return_value={}) @@ -178,15 +180,17 @@ class GroupSpecsTestCase(test.TestCase): fake.PROJECT_ID, use_admin_context=True, version=mv.GROUP_TYPE) - self.assertRaises(webob.exc.HTTPBadRequest, + self.assertRaises(exception.ValidationError, self.controller.update, req, fake.GROUP_TYPE_ID, - 'id') - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, - req, fake.GROUP_TYPE_ID, 'id', fake_group_specs) - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, - req, fake.GROUP_TYPE_ID, 'key1', fake_group_specs) + 'id', body=None) + self.assertRaises(exception.ValidationError, self.controller.update, + req, fake.GROUP_TYPE_ID, 'id', + body=fake_group_specs) + self.assertRaises(exception.ValidationError, self.controller.update, + req, fake.GROUP_TYPE_ID, 'key1', + body=fake_group_specs) @mock.patch.object(db, 'group_type_specs_get', return_value=fake_group_specs) @@ -216,5 +220,5 @@ class GroupSpecsTestCase(test.TestCase): fake.PROJECT_ID, use_admin_context=True, version=mv.GROUP_TYPE) - self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, - req, fake.GROUP_ID, incorrect_fake_group_specs) + self.assertRaises(exception.ValidationError, self.controller.create, + req, fake.GROUP_ID, body=incorrect_fake_group_specs)