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:
@@ -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': {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user