diff options
author | Nikola Dipanov <ndipanov@redhat.com> | 2013-05-30 12:49:56 +0200 |
---|---|---|
committer | Nikola Dipanov <ndipanov@redhat.com> | 2013-07-26 12:33:01 +0200 |
commit | e9fd70332e67810a7d89fbb1ddd73d8832090f61 (patch) | |
tree | 039fbc7d2a50af198be3f9a0485a7e508d923f26 /nova/block_device.py | |
parent | 8c3475706d22da09846fc98b0fc12ca81d2b22e5 (diff) | |
download | nova-e9fd70332e67810a7d89fbb1ddd73d8832090f61.tar.gz |
Add basic BDM format validation in the API layer
Adds the basic sanity checking for the new BDM data format when it's
passed in to the servers create method. Also make block_device routines
that raise IvalidBDMFormat error add a brief explanation to it that can
be reused to send more informative validation errors to the user.
More comprehensive validation that will take a look at the request as a
whole, and take into consideration all the metadata, will be done in
the compute API create method in the subsequent patches.
blueprint: improve-block-device-handling
Change-Id: Ie4c2c9a219be91faa07106f820a728ca9ac42e1b
Diffstat (limited to 'nova/block_device.py')
-rw-r--r-- | nova/block_device.py | 74 |
1 files changed, 68 insertions, 6 deletions
diff --git a/nova/block_device.py b/nova/block_device.py index 8ae396756b..4fbcc1b351 100644 --- a/nova/block_device.py +++ b/nova/block_device.py @@ -21,6 +21,8 @@ from oslo.config import cfg from nova import exception from nova.openstack.common import log as logging +from nova.openstack.common import strutils +from nova import utils from nova.virt import driver CONF = cfg.CONF @@ -72,6 +74,8 @@ class BlockDeviceDict(dict): _db_only_fields = (bdm_db_only_fields | bdm_db_inherited_fields) + _required_fields = set(['source_type']) + def __init__(self, bdm_dict=None, do_not_default=None): super(BlockDeviceDict, self).__init__() @@ -87,10 +91,39 @@ class BlockDeviceDict(dict): def _validate(self, bdm_dict): """Basic data format validations.""" - if (not set(key for key, _ in bdm_dict.iteritems()) <= + dict_fields = set(key for key, _ in bdm_dict.iteritems()) + + # Check that there are no bogus fields + if not (dict_fields <= (self._fields | self._db_only_fields)): - raise exception.InvalidBDMFormat() - # TODO(ndipanov): Validate must-have fields! + raise exception.InvalidBDMFormat( + details="Some fields are invalid.") + + if bdm_dict.get('no_device'): + return + + # Check that all required fields are there + if (self._required_fields and + not ((dict_fields & self._required_fields) == + self._required_fields)): + raise exception.InvalidBDMFormat( + details="Some required fields are missing") + + if 'delete_on_termination' in bdm_dict: + bdm_dict['delete_on_termination'] = strutils.bool_from_string( + bdm_dict['delete_on_termination']) + + if bdm_dict.get('device_name') is not None: + validate_device_name(bdm_dict['device_name']) + + validate_and_default_volume_size(bdm_dict) + + if bdm_dict.get('boot_index'): + try: + bdm_dict['boot_index'] = int(bdm_dict['boot_index']) + except ValueError: + raise exception.InvalidBDMFormat( + details="Boot index is invalid.") @classmethod def from_legacy(cls, legacy_bdm): @@ -133,7 +166,8 @@ class BlockDeviceDict(dict): pass else: - raise exception.InvalidBDMFormat() + raise exception.InvalidBDMFormat( + details="Unrecognized legacy format.") return cls(new_bdm, non_computable_fields) @@ -149,10 +183,12 @@ class BlockDeviceDict(dict): device_uuid = api_dict.get('uuid') if source_type not in ('volume', 'image', 'snapshot', 'blank'): - raise exception.InvalidBDMFormat() + raise exception.InvalidBDMFormat( + details="Invalid source_type field.") elif source_type != 'blank': if not device_uuid: - raise exception.InvalidBDMFormat() + raise exception.InvalidBDMFormat( + details="Missing device UUID.") api_dict[source_type + '_id'] = device_uuid api_dict.pop('uuid', None) @@ -256,6 +292,32 @@ def properties_root_device_name(properties): return root_device_name +def validate_device_name(value): + try: + # NOTE (ndipanov): Do not allow empty device names + # until assigning default values + # is supported by nova.compute + utils.check_string_length(value, 'Device name', + min_length=1, max_length=255) + except exception.InvalidInput as e: + raise exception.InvalidBDMFormat( + details="Device name empty or too long.") + + if ' ' in value: + raise exception.InvalidBDMFormat( + details="Device name contains spaces.") + + +def validate_and_default_volume_size(bdm): + if bdm.get('volume_size'): + try: + bdm['volume_size'] = utils.validate_integer( + bdm['volume_size'], 'volume_size', min_value=0) + except exception.InvalidInput as e: + raise exception.InvalidBDMFormat( + details="Invalid volume_size.") + + _ephemeral = re.compile('^ephemeral(\d|[1-9]\d+)$') |