Merge "Handle missing volume in handle_snapshot_delete"
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
@@ -19,6 +20,8 @@ from heat.engine.clients import progress
|
|||||||
from heat.engine import resource
|
from heat.engine import resource
|
||||||
from heat.engine import rsrc_defn
|
from heat.engine import rsrc_defn
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BaseVolume(resource.Resource):
|
class BaseVolume(resource.Resource):
|
||||||
"""Base Volume Manager."""
|
"""Base Volume Manager."""
|
||||||
@@ -95,8 +98,13 @@ class BaseVolume(resource.Resource):
|
|||||||
return prg
|
return prg
|
||||||
|
|
||||||
def _create_backup(self):
|
def _create_backup(self):
|
||||||
backup = self.client().backups.create(self.resource_id)
|
with self.client_plugin().ignore_not_found:
|
||||||
return backup.id
|
backup = self.client().backups.create(self.resource_id)
|
||||||
|
return backup.id
|
||||||
|
LOG.debug(
|
||||||
|
"Skip creating a backup for volume %s - NotFound",
|
||||||
|
self.resource_id)
|
||||||
|
return None
|
||||||
|
|
||||||
def _check_create_backup_complete(self, prg):
|
def _check_create_backup_complete(self, prg):
|
||||||
backup = self.client().backups.get(prg.backup_id)
|
backup = self.client().backups.get(prg.backup_id)
|
||||||
@@ -133,6 +141,8 @@ class BaseVolume(resource.Resource):
|
|||||||
if not prg.backup['called']:
|
if not prg.backup['called']:
|
||||||
prg.backup_id = self._create_backup()
|
prg.backup_id = self._create_backup()
|
||||||
prg.backup['called'] = True
|
prg.backup['called'] = True
|
||||||
|
if prg.backup_id is None:
|
||||||
|
prg.backup['complete'] = True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not prg.backup['complete']:
|
if not prg.backup['complete']:
|
||||||
|
@@ -25,6 +25,7 @@ from heat.common import template_format
|
|||||||
from heat.engine.clients.os import cinder
|
from heat.engine.clients.os import cinder
|
||||||
from heat.engine.clients.os import glance
|
from heat.engine.clients.os import glance
|
||||||
from heat.engine.clients.os import nova
|
from heat.engine.clients.os import nova
|
||||||
|
from heat.engine.clients import progress
|
||||||
from heat.engine.resources.openstack.cinder import volume as c_vol
|
from heat.engine.resources.openstack.cinder import volume as c_vol
|
||||||
from heat.engine.resources import scheduler_hints as sh
|
from heat.engine.resources import scheduler_hints as sh
|
||||||
from heat.engine import rsrc_defn
|
from heat.engine import rsrc_defn
|
||||||
@@ -1236,6 +1237,92 @@ class CinderVolumeTest(vt_base.VolumeTestCase):
|
|||||||
stack)
|
stack)
|
||||||
self.assertIsNone(rsrc.handle_delete_snapshot(mock_vs))
|
self.assertIsNone(rsrc.handle_delete_snapshot(mock_vs))
|
||||||
|
|
||||||
|
def test_check_delete_complete(self):
|
||||||
|
fb_creating = vt_base.FakeBackup('creating')
|
||||||
|
fb_available = vt_base.FakeBackup("available")
|
||||||
|
self.cinder_fc.backups.create.return_value = fb_creating
|
||||||
|
self.cinder_fc.backups.get.side_effect = [fb_creating, fb_available]
|
||||||
|
self.cinder_fc.volumes.get.side_effect = [
|
||||||
|
vt_base.FakeVolume('available'),
|
||||||
|
vt_base.FakeVolume('deleting'),
|
||||||
|
cinder_exp.NotFound("Nope")
|
||||||
|
]
|
||||||
|
# will need backup first
|
||||||
|
fake_prg = progress.VolumeDeleteProgress()
|
||||||
|
self.stack_name = 'test_volume_check_delete'
|
||||||
|
t = template_format.parse(single_cinder_volume_template)
|
||||||
|
stack = utils.parse_stack(t, stack_name=self.stack_name)
|
||||||
|
rsrc = c_vol.CinderVolume(
|
||||||
|
'volume',
|
||||||
|
stack.t.resource_definitions(stack)['volume'],
|
||||||
|
stack)
|
||||||
|
|
||||||
|
# first backup was called
|
||||||
|
self.assertFalse(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertFalse(fake_prg.backup["complete"])
|
||||||
|
self.assertFalse(fake_prg.delete["called"])
|
||||||
|
self.assertFalse(fake_prg.delete["complete"])
|
||||||
|
self.assertEqual(fake_prg.backup_id, fb_creating.id)
|
||||||
|
self.cinder_fc.backups.create.assert_called_once_with(rsrc.resource_id)
|
||||||
|
|
||||||
|
# polling for backup status
|
||||||
|
self.assertFalse(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertFalse(fake_prg.backup["complete"])
|
||||||
|
self.assertFalse(fake_prg.delete["called"])
|
||||||
|
self.assertFalse(fake_prg.delete["complete"])
|
||||||
|
self.cinder_fc.backups.get.assert_called_once_with(fb_creating.id)
|
||||||
|
self.assertFalse(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertTrue(fake_prg.backup["complete"])
|
||||||
|
self.assertFalse(fake_prg.delete["called"])
|
||||||
|
self.assertFalse(fake_prg.delete["complete"])
|
||||||
|
self.cinder_fc.backups.get.assert_called_with(fb_creating.id)
|
||||||
|
self.assertEqual(2, self.cinder_fc.backups.get.call_count)
|
||||||
|
|
||||||
|
# volume delete called, includes one volume get too
|
||||||
|
self.assertFalse(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertTrue(fake_prg.backup["complete"])
|
||||||
|
self.assertTrue(fake_prg.delete["called"])
|
||||||
|
self.assertFalse(fake_prg.delete["complete"])
|
||||||
|
self.cinder_fc.volumes.delete.assert_called_once_with(rsrc.resource_id)
|
||||||
|
self.cinder_fc.volumes.get.assert_called_with(rsrc.resource_id)
|
||||||
|
self.assertEqual(1, self.cinder_fc.volumes.get.call_count)
|
||||||
|
|
||||||
|
# polling for volume deleted
|
||||||
|
self.assertFalse(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertTrue(fake_prg.backup["complete"])
|
||||||
|
self.assertTrue(fake_prg.delete["called"])
|
||||||
|
self.assertFalse(fake_prg.delete["complete"])
|
||||||
|
self.cinder_fc.volumes.get.assert_called_with(rsrc.resource_id)
|
||||||
|
self.assertEqual(2, self.cinder_fc.volumes.get.call_count)
|
||||||
|
self.assertTrue(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertTrue(fake_prg.backup["complete"])
|
||||||
|
self.assertTrue(fake_prg.delete["called"])
|
||||||
|
self.assertTrue(fake_prg.delete["complete"])
|
||||||
|
self.cinder_fc.volumes.get.assert_called_with(rsrc.resource_id)
|
||||||
|
self.assertEqual(3, self.cinder_fc.volumes.get.call_count)
|
||||||
|
|
||||||
|
def test_check_delete_complete_snapshot_missing_volume(self):
|
||||||
|
self.cinder_fc.backups.create.side_effect = cinder_exp.NotFound("Nope")
|
||||||
|
fake_prg = progress.VolumeDeleteProgress()
|
||||||
|
self.stack_name = 'test_check_delete_complete_snapshot_missing_volume'
|
||||||
|
t = template_format.parse(single_cinder_volume_template)
|
||||||
|
stack = utils.parse_stack(t, stack_name=self.stack_name)
|
||||||
|
rsrc = c_vol.CinderVolume(
|
||||||
|
'volume',
|
||||||
|
stack.t.resource_definitions(stack)['volume'],
|
||||||
|
stack)
|
||||||
|
self.assertFalse(rsrc.check_delete_complete(fake_prg))
|
||||||
|
self.assertTrue(fake_prg.backup["called"])
|
||||||
|
self.assertTrue(fake_prg.backup["complete"])
|
||||||
|
self.assertIsNone(fake_prg.backup_id)
|
||||||
|
self.cinder_fc.backups.create.assert_called_once_with(rsrc.resource_id)
|
||||||
|
|
||||||
def test_vaildate_deletion_policy(self):
|
def test_vaildate_deletion_policy(self):
|
||||||
cfg.CONF.set_override('backups_enabled', False, group='volumes')
|
cfg.CONF.set_override('backups_enabled', False, group='volumes')
|
||||||
self.stack_name = 'test_volume_validate_deletion_policy'
|
self.stack_name = 'test_volume_validate_deletion_policy'
|
||||||
|
Reference in New Issue
Block a user