Implement OS::Cinder::VolumeAttachment

This creates a new volume attachment resource with Cinder specific
naming.

Change-Id: Ie73b929925c58e47f3509d57dd385cbd4ea5a4c1
This commit is contained in:
Thomas Herve 2013-05-21 10:27:15 +02:00
parent 19dccd770c
commit 5a8f731eeb
2 changed files with 80 additions and 10 deletions

View File

@ -102,7 +102,7 @@ class Volume(resource.Resource):
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:
@ -123,17 +123,18 @@ class VolumeAttachment(resource.Resource):
'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)
@ -143,8 +144,8 @@ class VolumeAttachment(resource.Resource):
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)
@ -200,9 +201,24 @@ class CinderVolume(Volume):
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,
}

View File

@ -225,7 +225,6 @@ class VolumeTest(HeatTestCase):
# 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',
@ -505,6 +504,61 @@ class VolumeTest(HeatTestCase):
'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'