diff --git a/mogan/api/controllers/v1/instances.py b/mogan/api/controllers/v1/instances.py index d353734a..6d8aca82 100644 --- a/mogan/api/controllers/v1/instances.py +++ b/mogan/api/controllers/v1/instances.py @@ -15,7 +15,6 @@ import datetime -import jsonschema from oslo_log import log from oslo_utils import netutils import pecan @@ -26,9 +25,12 @@ from wsme import types as wtypes from mogan.api.controllers import base from mogan.api.controllers import link +from mogan.api.controllers.v1.schemas import floating_ips as fip_schemas +from mogan.api.controllers.v1.schemas import instances as inst_schemas from mogan.api.controllers.v1 import types from mogan.api.controllers.v1 import utils as api_utils from mogan.api import expose +from mogan.api import validation from mogan.common import exception from mogan.common.i18n import _ from mogan.common.i18n import _LW @@ -43,56 +45,6 @@ _DEFAULT_INSTANCE_RETURN_FIELDS = ('uuid', 'name', 'description', LOG = log.getLogger(__name__) -_CREATE_INSTANCE_SCHEMA = { - "$schema": "http://json-schema.org/schema#", - "title": "Create instance schema", - "type": "object", - "properties": { - 'name': {'type': 'string', 'minLength': 1, 'maxLength': 255}, - 'description': {'type': 'string', 'minLength': 1, 'maxLength': 255}, - 'availability_zone': {'type': 'string', 'minLength': 1, - 'maxLength': 255}, - 'image_uuid': {'type': 'string', 'format': 'uuid'}, - 'instance_type_uuid': {'type': 'string', 'format': 'uuid'}, - 'networks': { - 'type': 'array', 'minItems': 1, - 'items': { - 'type': 'object', - 'properties': { - 'net_id': {'type': 'string', 'format': 'uuid'}, - 'port_type': {'type': 'string', 'minLength': 1, - 'maxLength': 255}, - }, - 'required': ['net_id'], - 'additionalProperties': False, - }, - }, - 'extra': { - 'type': 'object', - 'patternProperties': { - '^[a-zA-Z0-9-_:. ]{1,255}$': { - 'type': 'string', 'maxLength': 255 - } - }, - 'additionalProperties': False - } - }, - 'required': ['name', 'image_uuid', 'instance_type_uuid', 'networks'], - 'additionalProperties': False, -} - -_ASSOCIATE_FIP_SCHEMA = { - "$schema": "http://json-schema.org/schema#", - "title": "Associate floating ip schema", - 'type': 'object', - 'properties': { - 'address': {'type': 'string', 'format': 'ip-address'}, - 'fixed_address': {'type': 'string', 'format': 'ip-address'} - }, - 'required': ['address'], - 'additionalProperties': False -} - class InstanceStates(base.APIBase): """API representation of the states of a instance.""" @@ -203,8 +155,7 @@ class FloatingIPController(rest.RestController): :param floatingip: The floating IP within the request body. """ - # Add jsonschema validate - _check_create_body(floatingip, _ASSOCIATE_FIP_SCHEMA) + validation.check_schema(floatingip, fip_schemas.add_floating_ip) instance = self._resource or self._get_resource(instance_uuid) address = floatingip['address'] @@ -495,8 +446,7 @@ class InstanceController(rest.RestController): :param instance: a instance within the request body. """ - # Add jsonschema validate - _check_create_body(instance, _CREATE_INSTANCE_SCHEMA) + validation.check_schema(instance, inst_schemas.create_instance) requested_networks = instance.pop('networks', None) instance_type_uuid = instance.get('instance_type_uuid') @@ -579,19 +529,3 @@ class InstanceController(rest.RestController): """ rpc_instance = self._resource or self._get_resource(instance_uuid) pecan.request.engine_api.delete(pecan.request.context, rpc_instance) - - -def _check_create_body(body, schema): - """Ensure all necessary keys are present and correct in create body. - - Check that the user-specified create body is in the expected format and - include the required information. - - :param body: create body - :raises: InvalidParameterValue if validation of create body fails. - """ - try: - jsonschema.validate(body, schema) - except jsonschema.ValidationError as exc: - raise exception.InvalidParameterValue(_('Invalid create body: %s') % - exc) diff --git a/mogan/api/controllers/v1/schemas/__init__.py b/mogan/api/controllers/v1/schemas/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mogan/api/controllers/v1/schemas/floating_ips.py b/mogan/api/controllers/v1/schemas/floating_ips.py new file mode 100644 index 00000000..b3429f96 --- /dev/null +++ b/mogan/api/controllers/v1/schemas/floating_ips.py @@ -0,0 +1,28 @@ +# Copyright 2017 Huawei Technologies Co.,LTD. +# 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 mogan.api.validation import parameter_types + + +add_floating_ip = { + 'type': 'object', + 'properties': { + 'address': parameter_types.ip_address, + 'fixed_address': parameter_types.ip_address + }, + 'required': ['address'], + 'additionalProperties': False +} diff --git a/mogan/api/controllers/v1/schemas/instances.py b/mogan/api/controllers/v1/schemas/instances.py new file mode 100644 index 00000000..2be80658 --- /dev/null +++ b/mogan/api/controllers/v1/schemas/instances.py @@ -0,0 +1,44 @@ +# Copyright 2017 Huawei Technologies Co.,LTD. +# 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 mogan.api.validation import parameter_types + + +create_instance = { + "type": "object", + "properties": { + 'name': parameter_types.name, + 'description': parameter_types.description, + 'availability_zone': parameter_types.availability_zone, + 'image_uuid': parameter_types.image_id, + 'instance_type_uuid': parameter_types.instance_type_id, + 'networks': { + 'type': 'array', 'minItems': 1, + 'items': { + 'type': 'object', + 'properties': { + 'net_id': parameter_types.network_id, + 'port_type': parameter_types.port_type, + }, + 'required': ['net_id'], + 'additionalProperties': False, + }, + }, + 'extra': parameter_types.extra, + }, + 'required': ['name', 'image_uuid', 'instance_type_uuid', 'networks'], + 'additionalProperties': False, +} diff --git a/mogan/api/validation/__init__.py b/mogan/api/validation/__init__.py new file mode 100644 index 00000000..708ae7b6 --- /dev/null +++ b/mogan/api/validation/__init__.py @@ -0,0 +1,38 @@ +# Copyright 2017 Huawei Technologies Co.,LTD. +# 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. +""" +Request Body validating middleware. + +""" + +import jsonschema + +from mogan.common import exception + + +def check_schema(body, schema): + """Ensure all necessary keys are present and correct in create body. + + Check that the user-specified create body is in the expected format and + include the required information. + + :param body: create body + :raises: InvalidParameterValue if validation of create body fails. + """ + try: + jsonschema.validate(body, schema) + except jsonschema.ValidationError as exc: + raise exception.InvalidParameterValue(_('Invalid create body: %s') % + exc) diff --git a/mogan/api/validation/parameter_types.py b/mogan/api/validation/parameter_types.py new file mode 100644 index 00000000..7e5223d7 --- /dev/null +++ b/mogan/api/validation/parameter_types.py @@ -0,0 +1,84 @@ +# Copyright 2017 Huawei Technologies Co.,LTD. +# 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. +""" +Common parameter types for validating request Body. + +""" + + +name = { + 'type': 'string', 'minLength': 1, 'maxLength': 255, +} + + +description = { + 'type': ['string', 'null'], 'minLength': 0, 'maxLength': 255, +} + + +availability_zone = { + 'type': 'string', 'minLength': 1, 'maxLength': 255, +} + + +image_id = { + 'type': 'string', 'format': 'uuid' +} + + +network_id = { + 'type': 'string', 'format': 'uuid' +} + + +network_port_id = { + 'type': 'string', 'format': 'uuid' +} + + +port_type = { + 'type': 'string', 'minLength': 1, 'maxLength': 255, +} + + +instance_type_id = { + 'type': 'string', 'format': 'uuid' +} + + +extra = { + 'type': 'object', + 'patternProperties': { + '^[a-zA-Z0-9-_:. ]{1,255}$': { + 'type': 'string', 'maxLength': 255 + } + }, + 'additionalProperties': False +} + + +mac_address = { + 'type': 'string', + 'pattern': '^([0-9a-fA-F]{2})(:[0-9a-fA-F]{2}){5}$' +} + + +ip_address = { + 'type': 'string', + 'oneOf': [ + {'format': 'ipv4'}, + {'format': 'ipv6'} + ] +}