Merge "Validate OS::Nova::Server block_device_mapping property"

This commit is contained in:
Jenkins 2013-09-18 01:11:25 +00:00 committed by Gerrit Code Review
commit 6370a8790e
2 changed files with 78 additions and 4 deletions

View File

@ -360,14 +360,30 @@ class Server(resource.Resource):
if key_name:
nova_utils.get_keypair(self.nova(), key_name)
# either volume_id or snapshot_id needs to be specified, but not both
# for block device mapping.
bdm = self.properties.get('block_device_mapping') or []
bootable_vol = False
for mapping in bdm:
if mapping['device_name'] is 'vda':
bootable_vol = True
if mapping.get('volume_id') and mapping.get('snapshot_id'):
raise exception.ResourcePropertyConflict('volume_id',
'snapshot_id')
if not mapping.get('volume_id') and not mapping.get('snapshot_id'):
msg = _('Either volume_id or snapshot_id must be specified for'
' device mapping %s') % mapping['device_name']
raise exception.StackValidationFailed(message=msg)
# make sure the image exists if specified.
image = self.properties.get('image', None)
if image:
nova_utils.get_image_id(self.nova(), image)
else:
# TODO(sbaker) confirm block_device_mapping is populated
# for boot-by-volume (see LP bug #1215267)
pass
elif not image and not bootable_vol:
msg = _('Neither image nor bootable volume is specified for'
' instance %s') % self.name
raise exception.StackValidationFailed(message=msg)
def handle_delete(self):
'''

View File

@ -799,3 +799,61 @@ class ServersTest(HeatTestCase):
'delete_on_termination': True
}
]))
def test_validate_conflict_block_device_mapping_props(self):
stack_name = 'test_validate_conflict_block_device_mapping_props'
(t, stack) = self._setup_test_stack(stack_name)
bdm = [{'device_name': 'vdb', 'snapshot_id': '1234',
'volume_id': '1234'}]
t['Resources']['WebServer']['Properties']['block_device_mapping'] = bdm
server = servers.Server('server_create_image_err',
t['Resources']['WebServer'], stack)
self.m.StubOutWithMock(server, 'nova')
server.nova().MultipleTimes().AndReturn(self.fc)
self.m.ReplayAll()
self.assertRaises(exception.ResourcePropertyConflict, server.validate)
self.m.VerifyAll()
def test_validate_insufficient_block_device_mapping_props(self):
stack_name = 'test_validate_insufficient_block_device_mapping_props'
(t, stack) = self._setup_test_stack(stack_name)
bdm = [{'device_name': 'vdb', 'volume_size': '1',
'delete_on_termination': True}]
t['Resources']['WebServer']['Properties']['block_device_mapping'] = bdm
server = servers.Server('server_create_image_err',
t['Resources']['WebServer'], stack)
self.m.StubOutWithMock(server, 'nova')
server.nova().MultipleTimes().AndReturn(self.fc)
self.m.ReplayAll()
ex = self.assertRaises(exception.StackValidationFailed,
server.validate)
msg = 'Either volume_id or snapshot_id must be specified for device' +\
' mapping vdb'
self.assertEqual(msg, str(ex))
self.m.VerifyAll()
def test_validate_without_image_or_bootable_volume(self):
stack_name = 'test_validate_without_image_or_bootable_volume'
(t, stack) = self._setup_test_stack(stack_name)
del t['Resources']['WebServer']['Properties']['image']
bdm = [{'device_name': 'vdb', 'volume_id': '1234'}]
t['Resources']['WebServer']['Properties']['block_device_mapping'] = bdm
server = servers.Server('server_create_image_err',
t['Resources']['WebServer'], stack)
self.m.StubOutWithMock(server, 'nova')
server.nova().MultipleTimes().AndReturn(self.fc)
self.m.ReplayAll()
ex = self.assertRaises(exception.StackValidationFailed,
server.validate)
msg = 'Neither image nor bootable volume is specified for instance %s'\
% server.name
self.assertEqual(msg, str(ex))
self.m.VerifyAll()