From d5f1e90fcf4bf6c86ae0f6f603ff19cb14d3ee2f Mon Sep 17 00:00:00 2001 From: Peter Razumovsky Date: Mon, 22 Aug 2016 14:00:22 +0300 Subject: [PATCH] Ephemeral disk size support for server bdm_v2 Add new properties ephemeral_size and ephemeral_format to OS::Nova::Server block_device_mapping_v2 property. Change-Id: I89ece2d0e20993c39a6ab7def648c1163d8e5678 Closes-bug: #1614343 --- .../engine/resources/openstack/nova/server.py | 58 +++++++++++++++++-- heat/tests/openstack/nova/test_server.py | 16 ++++- ...ver-ephemeral-bdm-v2-55e0fe2afc5d8b63.yaml | 8 +++ 3 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/server-ephemeral-bdm-v2-55e0fe2afc5d8b63.yaml diff --git a/heat/engine/resources/openstack/nova/server.py b/heat/engine/resources/openstack/nova/server.py index c09365438d..5757a7307c 100644 --- a/heat/engine/resources/openstack/nova/server.py +++ b/heat/engine/resources/openstack/nova/server.py @@ -94,6 +94,8 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, BLOCK_DEVICE_MAPPING_BOOT_INDEX, BLOCK_DEVICE_MAPPING_VOLUME_SIZE, BLOCK_DEVICE_MAPPING_DELETE_ON_TERM, + BLOCK_DEVICE_MAPPING_EPHEMERAL_SIZE, + BLOCK_DEVICE_MAPPING_EPHEMERAL_FORMAT, ) = ( 'device_name', 'volume_id', @@ -106,6 +108,8 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, 'boot_index', 'volume_size', 'delete_on_termination', + 'ephemeral_size', + 'ephemeral_format' ) _NETWORK_KEYS = ( @@ -253,6 +257,24 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, properties.Schema.INTEGER, _('The size of the swap, in MB.') ), + BLOCK_DEVICE_MAPPING_EPHEMERAL_SIZE: properties.Schema( + properties.Schema.INTEGER, + _('The size of the local ephemeral block device, ' + 'in GB.'), + support_status=support.SupportStatus(version='8.0.0'), + constraints=[constraints.Range(min=1)] + ), + BLOCK_DEVICE_MAPPING_EPHEMERAL_FORMAT: properties.Schema( + properties.Schema.STRING, + _('The format of the local ephemeral block device. ' + 'If no format is specified, uses default value, ' + 'defined in nova configuration file.'), + constraints=[ + constraints.AllowedValues(['ext2', 'ext3', 'ext4', + 'xfs', 'ntfs']) + ], + support_status=support.SupportStatus(version='8.0.0') + ), BLOCK_DEVICE_MAPPING_DEVICE_TYPE: properties.Schema( properties.Schema.STRING, _('Device type: at the moment we can make distinction ' @@ -1093,6 +1115,22 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, 'volume_size': mapping.get( cls.BLOCK_DEVICE_MAPPING_SWAP_SIZE), } + elif (mapping.get(cls.BLOCK_DEVICE_MAPPING_EPHEMERAL_SIZE) or + mapping.get(cls.BLOCK_DEVICE_MAPPING_EPHEMERAL_FORMAT)): + bmd_dict = { + 'source_type': 'blank', + 'destination_type': 'local', + 'boot_index': -1, + 'delete_on_termination': True + } + ephemeral_size = mapping.get( + cls.BLOCK_DEVICE_MAPPING_EPHEMERAL_SIZE) + if ephemeral_size: + bmd_dict.update({'volume_size': ephemeral_size}) + ephemeral_format = mapping.get( + cls.BLOCK_DEVICE_MAPPING_EPHEMERAL_FORMAT) + if ephemeral_format: + bmd_dict.update({'guest_format': ephemeral_format}) # NOTE(prazumovsky): In case of server doesn't take empty value of # device name, need to escape from such situation. @@ -1452,19 +1490,27 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin, snapshot_id = mapping.get(self.BLOCK_DEVICE_MAPPING_SNAPSHOT_ID) image_id = mapping.get(self.BLOCK_DEVICE_MAPPING_IMAGE) swap_size = mapping.get(self.BLOCK_DEVICE_MAPPING_SWAP_SIZE) + ephemeral = (mapping.get( + self.BLOCK_DEVICE_MAPPING_EPHEMERAL_SIZE) or mapping.get( + self.BLOCK_DEVICE_MAPPING_EPHEMERAL_FORMAT)) - property_tuple = (volume_id, snapshot_id, image_id, swap_size) + property_tuple = (volume_id, snapshot_id, image_id, swap_size, + ephemeral) - if property_tuple.count(None) < 3: + if property_tuple.count(None) < 4: raise exception.ResourcePropertyConflict( self.BLOCK_DEVICE_MAPPING_VOLUME_ID, self.BLOCK_DEVICE_MAPPING_SNAPSHOT_ID, self.BLOCK_DEVICE_MAPPING_IMAGE, - self.BLOCK_DEVICE_MAPPING_SWAP_SIZE) + self.BLOCK_DEVICE_MAPPING_SWAP_SIZE, + self.BLOCK_DEVICE_MAPPING_EPHEMERAL_SIZE, + self.BLOCK_DEVICE_MAPPING_EPHEMERAL_FORMAT + ) - if property_tuple.count(None) == 4: - msg = _('Either volume_id, snapshot_id, image_id or ' - 'swap_size must be specified.') + if property_tuple.count(None) == 5: + msg = _('Either volume_id, snapshot_id, image_id, swap_size, ' + 'ephemeral_size or ephemeral_format must be ' + 'specified.') raise exception.StackValidationFailed(message=msg) if any((volume_id is not None, snapshot_id is not None, diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py index 389a0d293d..c430dae7a2 100644 --- a/heat/tests/openstack/nova/test_server.py +++ b/heat/tests/openstack/nova/test_server.py @@ -2727,6 +2727,18 @@ class ServersTest(common.HeatTestCase): {'device_name': ''} ])) + self.assertEqual([ + {'source_type': 'blank', + 'destination_type': 'local', + 'boot_index': -1, + 'delete_on_termination': True, + 'volume_size': 1, + 'guest_format': 'ext4'} + ], servers.Server._build_block_device_mapping_v2([ + {'ephemeral_size': 1, + 'ephemeral_format': 'ext4'} + ])) + def test_block_device_mapping_v2_image_resolve(self): (tmpl, stack) = self._setup_test_stack('mapping', test_templ=bdm_v2_template) @@ -2801,8 +2813,8 @@ class ServersTest(common.HeatTestCase): resource_defns['WebServer'], stack) exc = self.assertRaises(exception.StackValidationFailed, server.validate) - msg = ('Either volume_id, snapshot_id, image_id or swap_size must ' - 'be specified.') + msg = ('Either volume_id, snapshot_id, image_id, swap_size, ' + 'ephemeral_size or ephemeral_format must be specified.') self.assertEqual(msg, six.text_type(exc)) @mock.patch.object(nova.NovaClientPlugin, '_create') diff --git a/releasenotes/notes/server-ephemeral-bdm-v2-55e0fe2afc5d8b63.yaml b/releasenotes/notes/server-ephemeral-bdm-v2-55e0fe2afc5d8b63.yaml new file mode 100644 index 0000000000..0bfb5170c2 --- /dev/null +++ b/releasenotes/notes/server-ephemeral-bdm-v2-55e0fe2afc5d8b63.yaml @@ -0,0 +1,8 @@ +--- +features: + - OS::Nova::Server now supports ephemeral_size and ephemeral_format + properties for block_device_mapping_v2 property. Property ephemeral_size is + integer, that require flavor with ephemeral disk size greater that 0. + Property ephemeral_format is string with allowed values ext2, ext3, ext4, + xfs and ntfs for Windows guests; it is optional and if has no value, uses + default, defined in nova config file.