os.close(self.dst_fd)
self.stubs.Set(self.volume.driver, 'local_path', self.fake_local_path)
+ self.image_id = '70a599e0-31e7-49b7-b260-868f441e862b'
self.image_meta = {
- 'id': '70a599e0-31e7-49b7-b260-868f441e862b',
+ 'id': self.image_id,
'container_format': 'bare',
'disk_format': 'raw'
}
volume = db.volume_get(self.context, self.volume_id)
self.assertEqual(volume.status, 'available')
+ def test_copy_volume_to_image_driver_exception(self):
+ self.image_meta['id'] = self.image_id
+
+ image_service = fake_image.FakeImageService()
+ # create new image in queued state
+ queued_image_id = 'd5133f15-f753-41bd-920a-06b8c49275d9'
+ queued_image_meta = image_service.show(self.context, self.image_id)
+ queued_image_meta['id'] = queued_image_id
+ queued_image_meta['status'] = 'queued'
+ image_service.create(self.context, queued_image_meta)
+
+ # create new image in saving state
+ saving_image_id = '5c6eec33-bab4-4e7d-b2c9-88e2d0a5f6f2'
+ saving_image_meta = image_service.show(self.context, self.image_id)
+ saving_image_meta['id'] = saving_image_id
+ saving_image_meta['status'] = 'saving'
+ image_service.create(self.context, saving_image_meta)
+
+ # create volume
+ self.volume_attrs['status'] = 'available'
+ self.volume_attrs['instance_uuid'] = None
+ db.volume_create(self.context, self.volume_attrs)
+
+ with mock.patch.object(self.volume.driver,
+ 'copy_volume_to_image') as driver_copy_mock:
+ driver_copy_mock.side_effect = exception.VolumeDriverException(
+ "Error")
+
+ # test with image not in queued state
+ self.assertRaises(exception.VolumeDriverException,
+ self.volume.copy_volume_to_image,
+ self.context,
+ self.volume_id,
+ self.image_meta)
+ volume = db.volume_get(self.context, self.volume_id)
+ self.assertEqual(volume['status'], 'available')
+ # image shouldn't be deleted if it is not in queued state
+ image_service.show(self.context, self.image_id)
+
+ # test with image in queued state
+ self.assertRaises(exception.VolumeDriverException,
+ self.volume.copy_volume_to_image,
+ self.context,
+ self.volume_id,
+ queued_image_meta)
+ volume = db.volume_get(self.context, self.volume_id)
+ self.assertEqual(volume['status'], 'available')
+ # queued image should be deleted
+ self.assertRaises(exception.ImageNotFound,
+ image_service.show,
+ self.context,
+ queued_image_id)
+
+ # test with image in saving state
+ self.assertRaises(exception.VolumeDriverException,
+ self.volume.copy_volume_to_image,
+ self.context,
+ self.volume_id,
+ saving_image_meta)
+ volume = db.volume_get(self.context, self.volume_id)
+ self.assertEqual(volume['status'], 'available')
+ # image in saving state should be deleted
+ self.assertRaises(exception.ImageNotFound,
+ image_service.show,
+ self.context,
+ saving_image_id)
+
class GetActiveByWindowTestCase(BaseVolumeTestCase):
def setUp(self):
"""
payload = {'volume_id': volume_id, 'image_id': image_meta['id']}
+ image_service = None
try:
volume = self.db.volume_get(context, volume_id)
"image (%(image_id)s) successfully"),
{'volume_id': volume_id, 'image_id': image_id})
except Exception as error:
+ LOG.error(_("Error occurred while uploading volume %(volume_id)s "
+ "to image %(image_id)s."),
+ {'volume_id': volume_id, 'image_id': image_meta['id']})
+ if image_service is not None:
+ # Deletes the image if it is in queued or saving state
+ self._delete_image(context, image_meta['id'], image_service)
+
with excutils.save_and_reraise_exception():
payload['message'] = unicode(error)
finally:
self.db.volume_update(context, volume_id,
{'status': 'in-use'})
+ def _delete_image(self, context, image_id, image_service):
+ """Deletes an image stuck in queued or saving state."""
+ try:
+ image_meta = image_service.show(context, image_id)
+ image_status = image_meta.get('status')
+ if image_status == 'queued' or image_status == 'saving':
+ LOG.warn("Deleting image %(image_id)s in %(image_status)s "
+ "state.",
+ {'image_id': image_id,
+ 'image_status': image_status})
+ image_service.delete(context, image_id)
+ except Exception:
+ LOG.warn(_("Error occurred while deleting image %s."),
+ image_id, exc_info=True)
+
def initialize_connection(self, context, volume_id, connector):
"""Prepare volume for connection from host represented by connector.