if vol.status == 'in-use':
logger.warn('cant delete volume when in-use')
- raise exception.Error("Volume in use")
+ raise exception.Error('Volume in use')
self.cinder().volumes.delete(self.resource_id)
except clients.cinderclient.exceptions.NotFound:
'Required': True},
'VolumeId': {'Type': 'String',
'Required': True},
- 'Device': {'Type': "String",
+ 'Device': {'Type': 'String',
'Required': True,
'AllowedPattern': '/dev/vd[b-z]'}}
- def __init__(self, name, json_snippet, stack):
- super(VolumeAttachment, self).__init__(name, json_snippet, stack)
+ _instance_property = 'InstanceId'
+ _volume_property = 'VolumeId'
+ _device_property = 'Device'
def handle_create(self):
- server_id = self.properties['InstanceId']
- volume_id = self.properties['VolumeId']
- dev = self.properties['Device']
+ server_id = self.properties[self._instance_property]
+ volume_id = self.properties[self._volume_property]
+ dev = self.properties[self._device_property]
inst = self.stack.clients.attach_volume_to_instance(server_id,
volume_id,
dev)
return self.UPDATE_REPLACE
def handle_delete(self):
- server_id = self.properties['InstanceId']
- volume_id = self.properties['VolumeId']
+ server_id = self.properties[self._instance_property]
+ volume_id = self.properties[self._volume_property]
self.stack.clients.detach_volume_from_instance(server_id, volume_id)
return unicode(getattr(vol, key))
+class CinderVolumeAttachment(VolumeAttachment):
+
+ properties_schema = {'instance_uuid': {'Type': 'String',
+ 'Required': True},
+ 'volume_id': {'Type': 'String',
+ 'Required': True},
+ 'mountpoint': {'Type': 'String',
+ 'Required': True}}
+
+ _instance_property = 'instance_uuid'
+ _volume_property = 'volume_id'
+ _device_property = 'mountpoint'
+
+
def resource_mapping():
return {
'AWS::EC2::Volume': Volume,
'AWS::EC2::VolumeAttachment': VolumeAttachment,
'OS::Cinder::Volume': CinderVolume,
+ 'OS::Cinder::VolumeAttachment': CinderVolumeAttachment,
}
# create script
clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
- #clients.OpenStackClients.cinder().MultipleTimes().AndReturn(self.fc)
eventlet.sleep(1).MultipleTimes().AndReturn(None)
self.fc.volumes.create_server_volume(
device=u'/dev/vdc',
'The Referenced Attribute (DataVolume unknown) is incorrect.',
str(error))
+ def test_cinder_attachment(self):
+ fv = FakeVolume('creating', 'available')
+ fva = FakeVolume('attaching', 'in-use')
+ stack_name = 'test_volume_attach_stack'
+
+ # volume create
+ clients.OpenStackClients.cinder().MultipleTimes().AndReturn(
+ self.cinder_fc)
+ self.cinder_fc.volumes.create(
+ size=u'1', availability_zone='nova',
+ display_description='%s.DataVolume' % stack_name,
+ display_name='%s.DataVolume' % stack_name).AndReturn(fv)
+
+ # create script
+ clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
+ eventlet.sleep(1).MultipleTimes().AndReturn(None)
+ self.fc.volumes.create_server_volume(
+ device=u'/dev/vdc',
+ server_id=u'WikiDatabase',
+ volume_id=u'vol-123').AndReturn(fva)
+
+ self.cinder_fc.volumes.get('vol-123').AndReturn(fva)
+
+ # delete script
+ fva = FakeVolume('in-use', 'available')
+ self.fc.volumes.delete_server_volume('WikiDatabase',
+ 'vol-123').AndReturn(None)
+ self.cinder_fc.volumes.get('vol-123').AndReturn(fva)
+
+ self.m.ReplayAll()
+
+ t = template_format.parse(volume_template)
+ t['Resources']['DataVolume']['Properties']['AvailabilityZone'] = 'nova'
+ t['Resources']['MountPoint']['Properties'] = {
+ 'instance_uuid': {'Ref': 'WikiDatabase'},
+ 'volume_id': {'Ref': 'DataVolume'},
+ 'mountpoint': '/dev/vdc'
+ }
+ stack = parse_stack(t, stack_name=stack_name)
+
+ scheduler.TaskRunner(stack['DataVolume'].create)()
+ self.assertEqual(fv.status, 'available')
+ resource = vol.CinderVolumeAttachment('MountPoint',
+ t['Resources']['MountPoint'],
+ stack)
+ self.assertEqual(resource.validate(), None)
+ scheduler.TaskRunner(resource.create)()
+ self.assertEqual(resource.state, vol.VolumeAttachment.CREATE_COMPLETE)
+
+ self.assertEqual(resource.handle_update({}), vol.Volume.UPDATE_REPLACE)
+
+ self.assertEqual(resource.delete(), None)
+
+ self.m.VerifyAll()
+
class FakeVolume:
status = 'attaching'