Merge "Add validation for cinder volume"
This commit is contained in:
commit
27dec537fd
|
@ -353,6 +353,49 @@ class CinderVolume(vb.BaseVolume):
|
|||
def check_delete_snapshot_complete(self, delete_task):
|
||||
return delete_task.step()
|
||||
|
||||
def _build_exclusive_options(self):
|
||||
exclusive_options = []
|
||||
if self.properties.get(self.SNAPSHOT_ID):
|
||||
exclusive_options.append(self.SNAPSHOT_ID)
|
||||
if self.properties.get(self.SOURCE_VOLID):
|
||||
exclusive_options.append(self.SOURCE_VOLID)
|
||||
if self.properties.get(self.IMAGE):
|
||||
exclusive_options.append(self.IMAGE)
|
||||
if self.properties.get(self.IMAGE_REF):
|
||||
exclusive_options.append(self.IMAGE_REF)
|
||||
return exclusive_options
|
||||
|
||||
def _validate_create_sources(self):
|
||||
exclusive_options = self._build_exclusive_options()
|
||||
size = self.properties.get(self.SIZE)
|
||||
if not size and len(exclusive_options) != 1:
|
||||
msg = (_('If neither "%(backup_id)s" nor "%(size)s" is '
|
||||
'specified, you should specify only one of '
|
||||
'"%(image)s/%(image_ref)s", "%(source_vol)s" '
|
||||
'or "%(snapshot_id)s", but currently specified '
|
||||
'options: %(exclusive_options)s.')
|
||||
% {'backup_id': self.BACKUP_ID,
|
||||
'size': self.SIZE,
|
||||
'image': self.IMAGE,
|
||||
'image_ref': self.IMAGE_REF,
|
||||
'source_vol': self.SOURCE_VOLID,
|
||||
'snapshot_id': self.SNAPSHOT_ID,
|
||||
'exclusive_options': exclusive_options})
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
elif size and len(exclusive_options) > 1:
|
||||
msg = (_('If "%(backup_id)s" is not specified, you can specify '
|
||||
'"%(size)s" or/and one of "%(image)s/%(image_ref)s", '
|
||||
'"%(source_vol)s" or "%(snapshot_id)s", but currently '
|
||||
'specified options: %(exclusive_options)s.')
|
||||
% {'backup_id': self.BACKUP_ID,
|
||||
'size': self.SIZE,
|
||||
'image': self.IMAGE,
|
||||
'image_ref': self.IMAGE_REF,
|
||||
'source_vol': self.SOURCE_VOLID,
|
||||
'snapshot_id': self.SNAPSHOT_ID,
|
||||
'exclusive_options': exclusive_options})
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
def validate(self):
|
||||
"""Validate provided params."""
|
||||
res = super(CinderVolume, self).validate()
|
||||
|
@ -365,6 +408,15 @@ class CinderVolume(vb.BaseVolume):
|
|||
raise exception.StackValidationFailed(
|
||||
message=_('Scheduler hints are not supported by the current '
|
||||
'volume API.'))
|
||||
# can not specify both image and imageRef
|
||||
image = self.properties.get(self.IMAGE)
|
||||
imageRef = self.properties.get(self.IMAGE_REF)
|
||||
if image and imageRef:
|
||||
raise exception.ResourcePropertyConflict(self.IMAGE,
|
||||
self.IMAGE_REF)
|
||||
# if not create from backup, need to check other create sources
|
||||
if not self.properties.get(self.BACKUP_ID):
|
||||
self._validate_create_sources()
|
||||
|
||||
def handle_restore(self, defn, restore_data):
|
||||
backup_id = restore_data['resource_data']['backup_id']
|
||||
|
|
|
@ -119,10 +119,7 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
|
|||
size=1, availability_zone='nova',
|
||||
description='test_description',
|
||||
name='test_name',
|
||||
imageRef='46988116-6703-4623-9dbc-2bc6d284021b',
|
||||
snapshot_id='snap-123',
|
||||
metadata={'key': 'value'},
|
||||
source_volid='vol-012',
|
||||
volume_type='lvm').AndReturn(fv)
|
||||
self.cinder_fc.volumes.get(fv.id).AndReturn(fv)
|
||||
fv_ready = vt_base.FakeVolume('available', id=fv.id)
|
||||
|
@ -132,12 +129,6 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
|
|||
|
||||
self.t['resources']['volume']['properties'].update({
|
||||
'volume_type': 'lvm',
|
||||
# Note that specifying all these arguments doesn't work in
|
||||
# practice, as they are conflicting, but we just want to check they
|
||||
# are sent to the backend.
|
||||
'imageRef': '46988116-6703-4623-9dbc-2bc6d284021b',
|
||||
'snapshot_id': 'snap-123',
|
||||
'source_volid': 'vol-012',
|
||||
})
|
||||
stack = utils.parse_stack(self.t, stack_name=stack_name)
|
||||
self.create_volume(self.t, stack, 'volume')
|
||||
|
@ -894,6 +885,72 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
|
|||
'volume API.', six.text_type(ex))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_cinder_create_with_image_and_imageRef(self):
|
||||
stack_name = 'test_create_with_size_snapshot_and_image'
|
||||
stack = utils.parse_stack(self.t, stack_name=stack_name)
|
||||
vp = stack.t['Resources']['volume2']['Properties']
|
||||
vp['imageRef'] = 'image-456'
|
||||
vp['image'] = 'image-123'
|
||||
vp.pop('size')
|
||||
rsrc = stack['volume2']
|
||||
self.stub_ImageConstraint_validate()
|
||||
ex = self.assertRaises(exception.ResourcePropertyConflict,
|
||||
rsrc.validate)
|
||||
self.assertEqual("Cannot define the following properties at the same "
|
||||
"time: image, imageRef.",
|
||||
six.text_type(ex))
|
||||
|
||||
def test_cinder_create_with_size_snapshot_and_image(self):
|
||||
stack_name = 'test_create_with_size_snapshot_and_image'
|
||||
stack = utils.parse_stack(self.t, stack_name=stack_name)
|
||||
vp = stack.t['Resources']['volume2']['Properties']
|
||||
vp['snapshot_id'] = 'snapshot-123'
|
||||
vp['image'] = 'image-123'
|
||||
rsrc = stack['volume2']
|
||||
self.stub_ImageConstraint_validate()
|
||||
self.stub_SnapshotConstraint_validate()
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
rsrc.validate)
|
||||
self.assertIn('If "backup_id" is not specified, you can specify '
|
||||
'"size" or/and one of "image/imageRef", '
|
||||
'"source_volid" or "snapshot_id", but currently '
|
||||
'specified options: [\'snapshot_id\', \'image\']',
|
||||
six.text_type(ex))
|
||||
|
||||
def test_cinder_create_with_snapshot_and_source_volume(self):
|
||||
stack_name = 'test_create_with_snapshot_and_source_volume'
|
||||
stack = utils.parse_stack(self.t, stack_name=stack_name)
|
||||
vp = stack.t['Resources']['volume2']['Properties']
|
||||
vp['snapshot_id'] = 'snapshot-123'
|
||||
vp['source_volid'] = 'source_volume-123'
|
||||
vp.pop('size')
|
||||
rsrc = stack['volume2']
|
||||
self.stub_VolumeConstraint_validate()
|
||||
self.stub_SnapshotConstraint_validate()
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
rsrc.validate)
|
||||
self.assertIn('If neither "backup_id" nor "size" is specified, you '
|
||||
'should specify only one of "image/imageRef", '
|
||||
'"source_volid" or "snapshot_id", but currently '
|
||||
'specified options: [\'snapshot_id\', \'source_volid\']',
|
||||
six.text_type(ex))
|
||||
|
||||
def test_cinder_create_no_size_no_options(self):
|
||||
stack_name = 'test_create_no_size_no_options'
|
||||
stack = utils.parse_stack(self.t, stack_name=stack_name)
|
||||
vp = stack.t['Resources']['volume2']['Properties']
|
||||
vp.pop('size')
|
||||
rsrc = stack['volume2']
|
||||
self.stub_VolumeConstraint_validate()
|
||||
self.stub_SnapshotConstraint_validate()
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
rsrc.validate)
|
||||
self.assertIn('If neither "backup_id" nor "size" is specified, you '
|
||||
'should specify only one of "image/imageRef", '
|
||||
'"source_volid" or "snapshot_id", but currently '
|
||||
'specified options: []',
|
||||
six.text_type(ex))
|
||||
|
||||
def test_volume_restore(self):
|
||||
stack_name = 'test_cvolume_restore_stack'
|
||||
|
||||
|
|
Loading…
Reference in New Issue