Check for nova exception.Conflict rather than task_state
When detaching and attaching volumes nova would raise an
exception.Conflict, if attach and detach can't happen. Let's
use that to retry rather than using task_state.
Change-Id: I50904e4254568cd807b9ff18eef482cadb626ce5
Task: 40169
(cherry picked from commit 01c230e793
)
This commit is contained in:
parent
33972cce57
commit
991197e20e
|
@ -696,7 +696,9 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
|
||||||
volume_id=volume_id,
|
volume_id=volume_id,
|
||||||
device=device)
|
device=device)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
if self.is_client_exception(ex):
|
if self.is_conflict(ex):
|
||||||
|
return False
|
||||||
|
elif self.is_client_exception(ex):
|
||||||
raise exception.Error(_(
|
raise exception.Error(_(
|
||||||
"Failed to attach volume %(vol)s to server %(srv)s "
|
"Failed to attach volume %(vol)s to server %(srv)s "
|
||||||
"- %(err)s") % {'vol': volume_id,
|
"- %(err)s") % {'vol': volume_id,
|
||||||
|
@ -711,12 +713,15 @@ echo -e '%s\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
|
||||||
try:
|
try:
|
||||||
self.client().volumes.delete_server_volume(server_id, attach_id)
|
self.client().volumes.delete_server_volume(server_id, attach_id)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
if not (self.is_not_found(ex)
|
if self.is_conflict(ex):
|
||||||
or self.is_bad_request(ex)):
|
return False
|
||||||
|
elif not (self.is_not_found(ex)
|
||||||
|
or self.is_bad_request(ex)):
|
||||||
raise exception.Error(
|
raise exception.Error(
|
||||||
_("Could not detach attachment %(att)s "
|
_("Could not detach attachment %(att)s "
|
||||||
"from server %(srv)s.") % {'srv': server_id,
|
"from server %(srv)s.") % {'srv': server_id,
|
||||||
'att': attach_id})
|
'att': attach_id})
|
||||||
|
return True
|
||||||
|
|
||||||
def check_detach_volume_complete(self, server_id, attach_id):
|
def check_detach_volume_complete(self, server_id, attach_id):
|
||||||
"""Check that nova server lost attachment.
|
"""Check that nova server lost attachment.
|
||||||
|
|
|
@ -508,17 +508,9 @@ class CinderVolume(vb.BaseVolume, sh.SchedulerHintsMixin):
|
||||||
|
|
||||||
def _detach_volume_to_complete(self, prg_detach):
|
def _detach_volume_to_complete(self, prg_detach):
|
||||||
if not prg_detach.called:
|
if not prg_detach.called:
|
||||||
# Waiting OS-EXT-STS:task_state in server to become available for
|
prg_detach.called = self.client_plugin(
|
||||||
# detach
|
'nova').detach_volume(prg_detach.srv_id,
|
||||||
task_state = self.client_plugin('nova').fetch_server_attr(
|
prg_detach.attach_id)
|
||||||
prg_detach.srv_id, 'OS-EXT-STS:task_state')
|
|
||||||
# Wait till out of any resize steps (including resize_finish)
|
|
||||||
if task_state is not None and 'resize' in task_state:
|
|
||||||
prg_detach.called = False
|
|
||||||
else:
|
|
||||||
self.client_plugin('nova').detach_volume(prg_detach.srv_id,
|
|
||||||
prg_detach.attach_id)
|
|
||||||
prg_detach.called = True
|
|
||||||
return False
|
return False
|
||||||
if not prg_detach.cinder_complete:
|
if not prg_detach.cinder_complete:
|
||||||
prg_detach.cinder_complete = self.client_plugin(
|
prg_detach.cinder_complete = self.client_plugin(
|
||||||
|
@ -533,16 +525,8 @@ class CinderVolume(vb.BaseVolume, sh.SchedulerHintsMixin):
|
||||||
|
|
||||||
def _attach_volume_to_complete(self, prg_attach):
|
def _attach_volume_to_complete(self, prg_attach):
|
||||||
if not prg_attach.called:
|
if not prg_attach.called:
|
||||||
# Waiting OS-EXT-STS:task_state in server to become available for
|
prg_attach.called = self.client_plugin('nova').attach_volume(
|
||||||
# attach
|
prg_attach.srv_id, prg_attach.vol_id, prg_attach.device)
|
||||||
task_state = self.client_plugin('nova').fetch_server_attr(
|
|
||||||
prg_attach.srv_id, 'OS-EXT-STS:task_state')
|
|
||||||
# Wait till out of any resize steps (including resize_finish)
|
|
||||||
if task_state is not None and 'resize' in task_state:
|
|
||||||
prg_attach.called = False
|
|
||||||
else:
|
|
||||||
prg_attach.called = self.client_plugin('nova').attach_volume(
|
|
||||||
prg_attach.srv_id, prg_attach.vol_id, prg_attach.device)
|
|
||||||
return False
|
return False
|
||||||
if not prg_attach.complete:
|
if not prg_attach.complete:
|
||||||
prg_attach.complete = self.client_plugin(
|
prg_attach.complete = self.client_plugin(
|
||||||
|
@ -768,17 +752,8 @@ class CinderVolumeAttachment(vb.BaseVolumeAttachment):
|
||||||
prg_detach = progress.VolumeDetachProgress(
|
prg_detach = progress.VolumeDetachProgress(
|
||||||
server_id, volume_id, self.resource_id)
|
server_id, volume_id, self.resource_id)
|
||||||
|
|
||||||
# Waiting OS-EXT-STS:task_state in server to become available for
|
prg_detach.called = self.client_plugin(
|
||||||
# detach
|
'nova').detach_volume(server_id, self.resource_id)
|
||||||
server = self.client_plugin('nova').fetch_server(server_id)
|
|
||||||
task_state = getattr(server, 'OS-EXT-STS:task_state', None)
|
|
||||||
# Wait till out of any resize steps (including resize_finish)
|
|
||||||
if task_state is not None and 'resize' in task_state:
|
|
||||||
prg_detach.called = False
|
|
||||||
else:
|
|
||||||
self.client_plugin('nova').detach_volume(server_id,
|
|
||||||
self.resource_id)
|
|
||||||
prg_detach.called = True
|
|
||||||
|
|
||||||
if self.VOLUME_ID in prop_diff:
|
if self.VOLUME_ID in prop_diff:
|
||||||
volume_id = prop_diff.get(self.VOLUME_ID)
|
volume_id = prop_diff.get(self.VOLUME_ID)
|
||||||
|
@ -811,16 +786,8 @@ class CinderVolumeAttachment(vb.BaseVolumeAttachment):
|
||||||
self.resource_id)
|
self.resource_id)
|
||||||
return False
|
return False
|
||||||
if not prg_attach.called:
|
if not prg_attach.called:
|
||||||
# Waiting OS-EXT-STS:task_state in server to become available for
|
prg_attach.called = self.client_plugin('nova').attach_volume(
|
||||||
# attach
|
prg_attach.srv_id, prg_attach.vol_id, prg_attach.device)
|
||||||
server = self.client_plugin('nova').fetch_server(prg_attach.srv_id)
|
|
||||||
task_state = getattr(server, 'OS-EXT-STS:task_state', None)
|
|
||||||
# Wait till out of any resize steps (including resize_finish)
|
|
||||||
if task_state is not None and 'resize' in task_state:
|
|
||||||
prg_attach.called = False
|
|
||||||
else:
|
|
||||||
prg_attach.called = self.client_plugin('nova').attach_volume(
|
|
||||||
prg_attach.srv_id, prg_attach.vol_id, prg_attach.device)
|
|
||||||
return False
|
return False
|
||||||
if not prg_attach.complete:
|
if not prg_attach.complete:
|
||||||
prg_attach.complete = self.client_plugin(
|
prg_attach.complete = self.client_plugin(
|
||||||
|
|
|
@ -17,6 +17,7 @@ import json
|
||||||
|
|
||||||
from cinderclient import exceptions as cinder_exp
|
from cinderclient import exceptions as cinder_exp
|
||||||
import mock
|
import mock
|
||||||
|
from novaclient import exceptions as nova_exp
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
@ -907,7 +908,6 @@ class CinderVolumeTest(vt_base.VolumeTestCase):
|
||||||
fv1, fva,
|
fv1, fva,
|
||||||
vt_base.FakeVolume('available'), fv2])
|
vt_base.FakeVolume('available'), fv2])
|
||||||
self.stub_VolumeConstraint_validate()
|
self.stub_VolumeConstraint_validate()
|
||||||
|
|
||||||
# delete script
|
# delete script
|
||||||
self.fc.volumes.get_server_volume.side_effect = [
|
self.fc.volumes.get_server_volume.side_effect = [
|
||||||
fva, fva, fakes_nova.fake_exception()]
|
fva, fva, fakes_nova.fake_exception()]
|
||||||
|
@ -916,10 +916,12 @@ class CinderVolumeTest(vt_base.VolumeTestCase):
|
||||||
stack = utils.parse_stack(self.t, stack_name=self.stack_name)
|
stack = utils.parse_stack(self.t, stack_name=self.stack_name)
|
||||||
|
|
||||||
self.create_volume(self.t, stack, 'volume')
|
self.create_volume(self.t, stack, 'volume')
|
||||||
|
|
||||||
rsrc = self.create_attachment(self.t, stack, 'attachment')
|
rsrc = self.create_attachment(self.t, stack, 'attachment')
|
||||||
prg_detach = mock.MagicMock(cinder_complete=True, nova_complete=True)
|
prg_detach = mock.MagicMock(cinder_complete=True, nova_complete=True)
|
||||||
prg_attach = mock.MagicMock(called=False, srv_id='InstanceInResize')
|
prg_attach = mock.MagicMock(called=False, srv_id='InstanceInResize')
|
||||||
|
self.fc.volumes.create_server_volume.side_effect = [
|
||||||
|
nova_exp.Conflict('409')]
|
||||||
|
|
||||||
self.assertEqual(False,
|
self.assertEqual(False,
|
||||||
rsrc.check_update_complete((prg_detach, prg_attach)))
|
rsrc.check_update_complete((prg_detach, prg_attach)))
|
||||||
self.assertEqual(False, prg_attach.called)
|
self.assertEqual(False, prg_attach.called)
|
||||||
|
@ -1299,6 +1301,8 @@ class CinderVolumeTest(vt_base.VolumeTestCase):
|
||||||
self.cinder_fc.volumes.create.return_value = fv
|
self.cinder_fc.volumes.create.return_value = fv
|
||||||
fv_ready = vt_base.FakeVolume('available', id=fv.id)
|
fv_ready = vt_base.FakeVolume('available', id=fv.id)
|
||||||
self.cinder_fc.volumes.get.side_effect = [fv, fv_ready]
|
self.cinder_fc.volumes.get.side_effect = [fv, fv_ready]
|
||||||
|
self.fc.volumes.delete_server_volume.side_effect = [
|
||||||
|
nova_exp.Conflict('409')]
|
||||||
self.t['resources']['volume']['properties'].update({
|
self.t['resources']['volume']['properties'].update({
|
||||||
'volume_type': 'lvm',
|
'volume_type': 'lvm',
|
||||||
})
|
})
|
||||||
|
@ -1338,7 +1342,8 @@ class CinderVolumeTest(vt_base.VolumeTestCase):
|
||||||
self.cinder_fc.volumes.create.return_value = fv
|
self.cinder_fc.volumes.create.return_value = fv
|
||||||
fv_ready = vt_base.FakeVolume('available', id=fv.id)
|
fv_ready = vt_base.FakeVolume('available', id=fv.id)
|
||||||
self.cinder_fc.volumes.get.side_effect = [fv, fv_ready]
|
self.cinder_fc.volumes.get.side_effect = [fv, fv_ready]
|
||||||
|
self.fc.volumes.create_server_volume.side_effect = [
|
||||||
|
nova_exp.Conflict('409')]
|
||||||
self.t['resources']['volume']['properties'].update({
|
self.t['resources']['volume']['properties'].update({
|
||||||
'volume_type': 'lvm',
|
'volume_type': 'lvm',
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue