Implement OS::Cinder::VolumeAttachment
This creates a new volume attachment resource with Cinder specific naming. Change-Id: Ie73b929925c58e47f3509d57dd385cbd4ea5a4c1
This commit is contained in:
parent
19dccd770c
commit
5a8f731eeb
@ -102,7 +102,7 @@ class Volume(resource.Resource):
|
|||||||
|
|
||||||
if vol.status == 'in-use':
|
if vol.status == 'in-use':
|
||||||
logger.warn('cant delete volume when 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)
|
self.cinder().volumes.delete(self.resource_id)
|
||||||
except clients.cinderclient.exceptions.NotFound:
|
except clients.cinderclient.exceptions.NotFound:
|
||||||
@ -123,17 +123,18 @@ class VolumeAttachment(resource.Resource):
|
|||||||
'Required': True},
|
'Required': True},
|
||||||
'VolumeId': {'Type': 'String',
|
'VolumeId': {'Type': 'String',
|
||||||
'Required': True},
|
'Required': True},
|
||||||
'Device': {'Type': "String",
|
'Device': {'Type': 'String',
|
||||||
'Required': True,
|
'Required': True,
|
||||||
'AllowedPattern': '/dev/vd[b-z]'}}
|
'AllowedPattern': '/dev/vd[b-z]'}}
|
||||||
|
|
||||||
def __init__(self, name, json_snippet, stack):
|
_instance_property = 'InstanceId'
|
||||||
super(VolumeAttachment, self).__init__(name, json_snippet, stack)
|
_volume_property = 'VolumeId'
|
||||||
|
_device_property = 'Device'
|
||||||
|
|
||||||
def handle_create(self):
|
def handle_create(self):
|
||||||
server_id = self.properties['InstanceId']
|
server_id = self.properties[self._instance_property]
|
||||||
volume_id = self.properties['VolumeId']
|
volume_id = self.properties[self._volume_property]
|
||||||
dev = self.properties['Device']
|
dev = self.properties[self._device_property]
|
||||||
inst = self.stack.clients.attach_volume_to_instance(server_id,
|
inst = self.stack.clients.attach_volume_to_instance(server_id,
|
||||||
volume_id,
|
volume_id,
|
||||||
dev)
|
dev)
|
||||||
@ -143,8 +144,8 @@ class VolumeAttachment(resource.Resource):
|
|||||||
return self.UPDATE_REPLACE
|
return self.UPDATE_REPLACE
|
||||||
|
|
||||||
def handle_delete(self):
|
def handle_delete(self):
|
||||||
server_id = self.properties['InstanceId']
|
server_id = self.properties[self._instance_property]
|
||||||
volume_id = self.properties['VolumeId']
|
volume_id = self.properties[self._volume_property]
|
||||||
self.stack.clients.detach_volume_from_instance(server_id, volume_id)
|
self.stack.clients.detach_volume_from_instance(server_id, volume_id)
|
||||||
|
|
||||||
|
|
||||||
@ -200,9 +201,24 @@ class CinderVolume(Volume):
|
|||||||
return unicode(getattr(vol, key))
|
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():
|
def resource_mapping():
|
||||||
return {
|
return {
|
||||||
'AWS::EC2::Volume': Volume,
|
'AWS::EC2::Volume': Volume,
|
||||||
'AWS::EC2::VolumeAttachment': VolumeAttachment,
|
'AWS::EC2::VolumeAttachment': VolumeAttachment,
|
||||||
'OS::Cinder::Volume': CinderVolume,
|
'OS::Cinder::Volume': CinderVolume,
|
||||||
|
'OS::Cinder::VolumeAttachment': CinderVolumeAttachment,
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,6 @@ class VolumeTest(HeatTestCase):
|
|||||||
|
|
||||||
# create script
|
# create script
|
||||||
clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
|
clients.OpenStackClients.nova().MultipleTimes().AndReturn(self.fc)
|
||||||
#clients.OpenStackClients.cinder().MultipleTimes().AndReturn(self.fc)
|
|
||||||
eventlet.sleep(1).MultipleTimes().AndReturn(None)
|
eventlet.sleep(1).MultipleTimes().AndReturn(None)
|
||||||
self.fc.volumes.create_server_volume(
|
self.fc.volumes.create_server_volume(
|
||||||
device=u'/dev/vdc',
|
device=u'/dev/vdc',
|
||||||
@ -505,6 +504,61 @@ class VolumeTest(HeatTestCase):
|
|||||||
'The Referenced Attribute (DataVolume unknown) is incorrect.',
|
'The Referenced Attribute (DataVolume unknown) is incorrect.',
|
||||||
str(error))
|
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:
|
class FakeVolume:
|
||||||
status = 'attaching'
|
status = 'attaching'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user