Add json-schema for v2.1 fixed-ips

This patch adds json-schema for v2.1 fixed-ips. The json-schame limits
the input for actions reserve/unreserve. Also fixed the API sample
file at same time and add parameter_type none.

Co-Authored-By: Ken'ichi Ohmichi <ken1ohmichi@gmail.com>
Change-Id: Id2d0416c3ccc2a50d3cb66bed8747082f98fb194
Closes-Bug: #1438480
This commit is contained in:
He Jie Xu 2015-04-01 00:47:14 +00:00
parent 739f471264
commit 8423a9cd15
11 changed files with 100 additions and 18 deletions

View File

@ -1,3 +1,3 @@
{
"reserve": "None"
"reserve": null
}

View File

@ -1,3 +1,3 @@
{
"reserve": "None"
"reserve": null
}

View File

@ -15,8 +15,10 @@
import webob
import webob.exc
from nova.api.openstack.compute.schemas.v3 import fixed_ips
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api import validation
from nova import exception
from nova.i18n import _
from nova import objects
@ -60,6 +62,7 @@ class FixedIPController(wsgi.Controller):
@wsgi.response(202)
@extensions.expected_errors((400, 404))
@validation.schema(fixed_ips.reserve)
@wsgi.action('reserve')
def reserve(self, req, id, body):
context = req.environ['nova.context']
@ -69,6 +72,7 @@ class FixedIPController(wsgi.Controller):
@wsgi.response(202)
@extensions.expected_errors((400, 404))
@validation.schema(fixed_ips.unreserve)
@wsgi.action('unreserve')
def unreserve(self, req, id, body):
context = req.environ['nova.context']

View File

@ -0,0 +1,36 @@
# 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 nova.api.validation import parameter_types
reserve = {
'type': 'object',
'properties': {
'reserve': parameter_types.none,
},
'required': ['reserve'],
'additionalProperties': False,
}
unreserve = {
'type': 'object',
'properties': {
'unreserve': parameter_types.none,
},
'required': ['unreserve'],
'additionalProperties': False,
}

View File

@ -62,6 +62,11 @@ boolean = {
}
none = {
'enum': ['None', None, {}]
}
positive_integer = {
'type': ['integer', 'string'],
'pattern': '^[0-9]*$', 'minimum': 1

View File

@ -1,3 +1,3 @@
{
"reserve": "%(reserve)s"
"reserve": null
}

View File

@ -1204,10 +1204,8 @@ class FixedIpJsonTest(ApiSampleTestBaseV2):
def test_fixed_ip_reserve(self):
# Reserve a Fixed IP.
project = {'reserve': None}
response = self._do_post('os-fixed-ips/192.168.1.1/action',
'fixedip-post-req',
project)
'fixedip-post-req', {})
self.assertEqual(response.status_code, 202)
self.assertEqual(response.content, "")

View File

@ -1,3 +1,3 @@
{
"reserve": "%(reserve)s"
"reserve": null
}

View File

@ -80,10 +80,8 @@ class FixedIpTest(test_servers.ServersSampleBase):
def test_fixed_ip_reserve(self):
# Reserve a Fixed IP.
project = {'reserve': None}
response = self._do_post('os-fixed-ips/192.168.1.1/action',
'fixedip-post-req',
project)
'fixedip-post-req', {})
self.assertEqual(response.status_code, 202)
self.assertEqual(response.content, "")

View File

@ -168,7 +168,7 @@ class FixedIpTestV21(test.NoDBTestCase):
body = {'reserve': None}
req = fakes.HTTPRequest.blank('%s/192.168.1.1/action' % self.url)
action = self._get_reserve_action()
result = action(req, "192.168.1.1", body)
result = action(req, "192.168.1.1", body=body)
self._assert_equal(result or action, 202)
self.assertEqual(fake_fixed_ips[0]['reserved'], True)
@ -179,7 +179,7 @@ class FixedIpTestV21(test.NoDBTestCase):
action = self._get_reserve_action()
self.assertRaises(webob.exc.HTTPNotFound, action, req,
'10.0.0.1', body)
'10.0.0.1', body=body)
def test_fixed_ip_reserve_invalid_ip_address(self):
body = {'reserve': None}
@ -187,7 +187,7 @@ class FixedIpTestV21(test.NoDBTestCase):
action = self._get_reserve_action()
self.assertRaises(webob.exc.HTTPBadRequest,
action, req, 'inv.ali.d.ip', body)
action, req, 'inv.ali.d.ip', body=body)
def test_fixed_ip_reserve_deleted_ip(self):
body = {'reserve': None}
@ -195,14 +195,14 @@ class FixedIpTestV21(test.NoDBTestCase):
req = fakes.HTTPRequest.blank('%s/10.0.0.2/action' % self.url)
self.assertRaises(webob.exc.HTTPNotFound, action, req,
'10.0.0.2', body)
'10.0.0.2', body=body)
def test_fixed_ip_unreserve(self):
fake_fixed_ips[0]['reserved'] = True
body = {'unreserve': None}
req = fakes.HTTPRequest.blank('%s/192.168.1.1/action' % self.url)
action = self._get_unreserve_action()
result = action(req, "192.168.1.1", body)
result = action(req, "192.168.1.1", body=body)
self._assert_equal(result or action, 202)
self.assertEqual(fake_fixed_ips[0]['reserved'], False)
@ -213,21 +213,21 @@ class FixedIpTestV21(test.NoDBTestCase):
action = self._get_unreserve_action()
self.assertRaises(webob.exc.HTTPNotFound, action, req,
'10.0.0.1', body)
'10.0.0.1', body=body)
def test_fixed_ip_unreserve_invalid_ip_address(self):
body = {'unreserve': None}
req = fakes.HTTPRequest.blank('%s/inv.ali.d.ip/action' % self.url)
action = self._get_unreserve_action()
self.assertRaises(webob.exc.HTTPBadRequest,
action, req, 'inv.ali.d.ip', body)
action, req, 'inv.ali.d.ip', body=body)
def test_fixed_ip_unreserve_deleted_ip(self):
body = {'unreserve': None}
req = fakes.HTTPRequest.blank('%s/10.0.0.2/action' % self.url)
action = self._get_unreserve_action()
self.assertRaises(webob.exc.HTTPNotFound, action, req,
'10.0.0.2', body)
'10.0.0.2', body=body)
class FixedIpTestV2(FixedIpTestV21):

View File

@ -621,6 +621,47 @@ class NameTestCase(APIValidationTestCase):
pass
class NoneTypeTestCase(APIValidationTestCase):
def setUp(self):
super(NoneTypeTestCase, self).setUp()
schema = {
'type': 'object',
'properties': {
'foo': parameter_types.none
}
}
@validation.schema(request_body_schema=schema)
def post(req, body):
return 'Validation succeeded.'
self.post = post
def test_validate_none(self):
self.assertEqual('Validation succeeded.',
self.post(body={'foo': 'None'},
req=FakeRequest()))
self.assertEqual('Validation succeeded.',
self.post(body={'foo': None},
req=FakeRequest()))
self.assertEqual('Validation succeeded.',
self.post(body={'foo': {}},
req=FakeRequest()))
def test_validate_none_fails(self):
detail = ("Invalid input for field/attribute foo. Value: ."
" '' is not one of ['None', None, {}]")
self.check_validation_error(self.post, body={'foo': ''},
expected_detail=detail)
detail = ("Invalid input for field/attribute foo. Value: "
"{'key': 'val'}. {'key': 'val'} is not one of "
"['None', None, {}]")
self.check_validation_error(self.post, body={'foo': {'key': 'val'}},
expected_detail=detail)
class TcpUdpPortTestCase(APIValidationTestCase):
def setUp(self):