Add validations for volume_size and destination_type

Add validations for volume_size and destination_type of
block device mapping when creating an instance
in order to avoid HTTP 500 errors.
Validations has been added in V2.1 API only.
Validations that has been added are as follows:

* volume_size: an empty string
* volume_size: zero
* volume_size: greater than DB column's limit
* destination_type: an empty string
* destination_type: invalid value

Change-Id: I2d3084cccd15f409616031f106c611ff07ac4abf
Closes-Bug: #1525806
This commit is contained in:
Takashi NATSUME
2016-03-14 14:26:11 +09:00
parent b87e6723ef
commit 9ad3dad0c6
5 changed files with 67 additions and 4 deletions
@@ -16,6 +16,7 @@ import copy
from nova.api.openstack.compute.schemas import block_device_mapping_v1
from nova.api.validation import parameter_types
from nova.objects import fields
block_device_mapping_new_item = {
@@ -35,7 +36,8 @@ block_device_mapping_new_item = {
# Defined as varchar(255) in column "destination_type" in table
# "block_device_mapping"
'destination_type': {
'type': 'string', 'maxLength': 255,
'type': 'string',
'enum': fields.BlockDeviceDestinationType.ALL,
},
# Defined as varchar(255) in column "guest_format" in table
# "block_device_mapping"
@@ -22,7 +22,7 @@ legacy_block_device_mapping = {
},
'volume_id': parameter_types.volume_id,
'snapshot_id': parameter_types.image_id,
'volume_size': parameter_types.non_negative_integer,
'volume_size': parameter_types.volume_size,
# Do not allow empty device names and number values and
# containing spaces(defined in nova/block_device.py:from_api())
'device_name': {
+9
View File
@@ -21,6 +21,7 @@ import unicodedata
import six
from nova import db
from nova.i18n import _
@@ -347,3 +348,11 @@ ipv6 = {
cidr = {
'type': 'string', 'format': 'cidr'
}
volume_size = {
'type': ['integer', 'string'],
'pattern': '^[0-9]+$',
'minimum': 1,
'maximum': db.MAX_INT
}
@@ -231,6 +231,20 @@ class BlockDeviceMappingTestV21(test.TestCase):
self.assertRaises(self.validation_error,
self._test_create, params, no_image=True)
def _test_create_instance_with_destination_type_error(self,
destination_type):
self.bdm[0]['destination_type'] = destination_type
params = {block_device_mapping.ATTRIBUTE_NAME: self.bdm}
self.assertRaises(self.validation_error,
self._test_create, params, no_image=True)
def test_create_instance_with_destination_type_empty_string(self):
self._test_create_instance_with_destination_type_error('')
def test_create_instance_with_invalid_destination_type(self):
self._test_create_instance_with_destination_type_error('fake')
def test_create_instance_bdm(self):
bdm = [{
'source_type': 'volume',
@@ -361,3 +375,13 @@ class BlockDeviceMappingTestV2(BlockDeviceMappingTestV21):
params = {block_device_mapping.ATTRIBUTE_NAME: bdm}
self._test_create(params,
override_controller=self.no_bdm_v2_controller)
def test_create_instance_with_destination_type_empty_string(self):
# Add a check whether the destination type is an empty string
# in V2.1 API only. So this test is skipped in V2.0 API
pass
def test_create_instance_with_invalid_destination_type(self):
# Add a check whether the destination type is invalid
# in V2.1 API only. So this test is skipped in V2.0 API
pass
@@ -26,6 +26,7 @@ from nova.api.openstack.compute.legacy_v2 import extensions
from nova.api.openstack.compute.legacy_v2 import servers as servers_v2
from nova.api.openstack.compute import servers as servers_v21
from nova.compute import api as compute_api
from nova import db
from nova import exception
from nova import test
from nova.tests.unit.api.openstack import fakes
@@ -243,10 +244,10 @@ class BlockDeviceMappingTestV21(test.TestCase):
self.assertRaises(self.validation_error,
self._test_create, params)
def test_create_instance_with_invalid_size(self):
def _test_create_instance_with_size_error(self, size):
bdm = [{'delete_on_termination': True,
'device_name': 'vda',
'volume_size': "hello world",
'volume_size': size,
'volume_id': '11111111-1111-1111-1111-111111111111'}]
params = {'block_device_mapping': bdm}
old_create = compute_api.API.create
@@ -259,6 +260,18 @@ class BlockDeviceMappingTestV21(test.TestCase):
self.assertRaises(self.validation_error,
self._test_create, params)
def test_create_instance_with_invalid_size(self):
self._test_create_instance_with_size_error("hello world")
def test_create_instance_with_size_empty_string(self):
self._test_create_instance_with_size_error('')
def test_create_instance_with_size_zero(self):
self._test_create_instance_with_size_error("0")
def test_create_instance_with_size_greater_than_limit(self):
self._test_create_instance_with_size_error(db.MAX_INT + 1)
def test_create_instance_with_bdm_delete_on_termination(self):
bdm = [{'device_name': 'foo1', 'volume_id': fakes.FAKE_UUID,
'delete_on_termination': 'True'},
@@ -395,3 +408,18 @@ class BlockDeviceMappingTestV2(BlockDeviceMappingTestV21):
params = {'block_device_mapping': bdm}
self._test_create(params, override_controller=controller)
def test_create_instance_with_size_empty_string(self):
# Add a check whether the size is an empty string
# in V2.1 API only. So this test is skipped in V2.0 API
pass
def test_create_instance_with_size_zero(self):
# Add a check whether the size is zero in V2.1 API only.
# So this test is skipped in V2.0 API
pass
def test_create_instance_with_size_greater_than_limit(self):
# Add a check whether size is greater than the limit
# in V2.1 API only. So this test is skipped in V2.0 API
pass