Merge "Allow suspend and resume again if failed last time"
This commit is contained in:
commit
3a47b49dd4
|
@ -942,7 +942,10 @@ class Resource(object):
|
|||
action = self.SUSPEND
|
||||
|
||||
# Don't try to suspend the resource unless it's in a stable state
|
||||
if (self.action == self.DELETE or self.status != self.COMPLETE):
|
||||
# or if the previous suspend failed
|
||||
if (self.action == self.DELETE or
|
||||
(self.action != self.SUSPEND and
|
||||
self.status != self.COMPLETE)):
|
||||
exc = exception.Error(_('State %s invalid for suspend')
|
||||
% six.text_type(self.state))
|
||||
raise exception.ResourceFailure(exc, self, action)
|
||||
|
@ -957,12 +960,15 @@ class Resource(object):
|
|||
'''
|
||||
action = self.RESUME
|
||||
|
||||
# Can't resume a resource unless it's SUSPEND_COMPLETE
|
||||
if self.state != (self.SUSPEND, self.COMPLETE):
|
||||
# Allow resume a resource if it's SUSPEND_COMPLETE
|
||||
# or RESUME_FAILED or RESUME_COMPLETE. Recommend to check
|
||||
# the real state of physical resource in handle_resume()
|
||||
if self.state not in ((self.SUSPEND, self.COMPLETE),
|
||||
(self.RESUME, self.FAILED),
|
||||
(self.RESUME, self.COMPLETE)):
|
||||
exc = exception.Error(_('State %s invalid for resume')
|
||||
% six.text_type(self.state))
|
||||
raise exception.ResourceFailure(exc, self, action)
|
||||
|
||||
LOG.info(_LI('resuming %s'), six.text_type(self))
|
||||
return self._do_action(action)
|
||||
|
||||
|
|
|
@ -795,8 +795,11 @@ class Instance(resource.Resource):
|
|||
else:
|
||||
raise
|
||||
else:
|
||||
LOG.debug("suspending instance %s" % self.resource_id)
|
||||
server.suspend()
|
||||
# if the instance has been suspended successful,
|
||||
# no need to suspend again
|
||||
if self.client_plugin().get_status(server) != 'SUSPENDED':
|
||||
LOG.debug("suspending instance %s" % self.resource_id)
|
||||
server.suspend()
|
||||
return server.id
|
||||
|
||||
def check_suspend_complete(self, server_id):
|
||||
|
@ -834,8 +837,11 @@ class Instance(resource.Resource):
|
|||
else:
|
||||
raise
|
||||
else:
|
||||
LOG.debug("resuming instance %s" % self.resource_id)
|
||||
server.resume()
|
||||
# if the instance has been resumed successful,
|
||||
# no need to resume again
|
||||
if self.client_plugin().get_status(server) != 'ACTIVE':
|
||||
LOG.debug("resuming instance %s" % self.resource_id)
|
||||
server.resume()
|
||||
return server.id
|
||||
|
||||
def check_resume_complete(self, server_id):
|
||||
|
|
|
@ -1405,8 +1405,11 @@ class Server(stack_user.StackUser):
|
|||
else:
|
||||
raise
|
||||
else:
|
||||
LOG.debug('suspending server %s' % self.resource_id)
|
||||
server.suspend()
|
||||
# if the server has been suspended successful,
|
||||
# no need to suspend again
|
||||
if self.client_plugin().get_status(server) != 'SUSPENDED':
|
||||
LOG.debug('suspending server %s' % self.resource_id)
|
||||
server.suspend()
|
||||
return server.id
|
||||
|
||||
def check_suspend_complete(self, server_id):
|
||||
|
@ -1444,8 +1447,11 @@ class Server(stack_user.StackUser):
|
|||
else:
|
||||
raise
|
||||
else:
|
||||
LOG.debug('resuming server %s' % self.resource_id)
|
||||
server.resume()
|
||||
# if the server has been resumed successful,
|
||||
# no need to resume again
|
||||
if self.client_plugin().get_status(server) != 'ACTIVE':
|
||||
LOG.debug('resuming server %s' % self.resource_id)
|
||||
server.resume()
|
||||
return server.id
|
||||
|
||||
def check_resume_complete(self, server_id):
|
||||
|
|
|
@ -1013,16 +1013,14 @@ class InstancesTest(common.HeatTestCase):
|
|||
scheduler.TaskRunner(instance.create)()
|
||||
self.assertEqual((instance.CREATE, instance.COMPLETE), instance.state)
|
||||
|
||||
def test_instance_status_suspend(self):
|
||||
def _test_instance_status_suspend(self, name,
|
||||
state=('CREATE', 'COMPLETE')):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
instance = self._create_test_instance(return_server,
|
||||
'in_suspend_wait')
|
||||
instance = self._create_test_instance(return_server, name)
|
||||
|
||||
instance.resource_id = '1234'
|
||||
self.m.ReplayAll()
|
||||
instance.state_set(state[0], state[1])
|
||||
|
||||
# Override the get_servers_1234 handler status to SUSPENDED, but
|
||||
# return the ACTIVE state first (twice, so we sleep)
|
||||
d1 = {'server': self.fc.client.get_servers_detail()[1]['servers'][0]}
|
||||
d2 = copy.deepcopy(d1)
|
||||
d1['server']['status'] = 'ACTIVE'
|
||||
|
@ -1039,16 +1037,28 @@ class InstancesTest(common.HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_instance_status_resume(self):
|
||||
def test_instance_suspend_in_create_complete(self):
|
||||
self._test_instance_status_suspend(
|
||||
name='test_suspend_in_create_complete')
|
||||
|
||||
def test_instance_suspend_in_suspend_failed(self):
|
||||
self._test_instance_status_suspend(
|
||||
name='test_suspend_in_suspend_failed',
|
||||
state=('SUSPEND', 'FAILED'))
|
||||
|
||||
def test_server_suspend_in_suspend_complete(self):
|
||||
self._test_instance_status_suspend(
|
||||
name='test_suspend_in_suspend_complete',
|
||||
state=('SUSPEND', 'COMPLETE'))
|
||||
|
||||
def _test_instance_status_resume(self, name,
|
||||
state=('SUSPEND', 'COMPLETE')):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
instance = self._create_test_instance(return_server,
|
||||
'in_resume_wait')
|
||||
instance = self._create_test_instance(return_server, name)
|
||||
|
||||
instance.resource_id = '1234'
|
||||
self.m.ReplayAll()
|
||||
instance.state_set(state[0], state[1])
|
||||
|
||||
# Override the get_servers_1234 handler status to ACTIVE, but
|
||||
# return the SUSPENDED state first (twice, so we sleep)
|
||||
d1 = {'server': self.fc.client.get_servers_detail()[1]['servers'][0]}
|
||||
d2 = copy.deepcopy(d1)
|
||||
d1['server']['status'] = 'SUSPENDED'
|
||||
|
@ -1067,6 +1077,20 @@ class InstancesTest(common.HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_instance_resume_in_suspend_complete(self):
|
||||
self._test_instance_status_resume(
|
||||
name='test_resume_in_suspend_complete')
|
||||
|
||||
def test_instance_resume_in_resume_failed(self):
|
||||
self._test_instance_status_resume(
|
||||
name='test_resume_in_resume_failed',
|
||||
state=('RESUME', 'FAILED'))
|
||||
|
||||
def test_instance_resume_in_resume_complete(self):
|
||||
self._test_instance_status_resume(
|
||||
name='test_resume_in_resume_complete',
|
||||
state=('RESUME', 'COMPLETE'))
|
||||
|
||||
def test_server_resume_other_exception(self):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
instance = self._create_test_instance(return_server,
|
||||
|
|
|
@ -1905,16 +1905,13 @@ class ServersTest(common.HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_server_status_suspend(self):
|
||||
def _test_server_status_suspend(self, name, state=('CREATE', 'COMPLETE')):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
server = self._create_test_server(return_server,
|
||||
'srv_susp_w')
|
||||
server = self._create_test_server(return_server, name)
|
||||
|
||||
server.resource_id = '1234'
|
||||
self.m.ReplayAll()
|
||||
server.state_set(state[0], state[1])
|
||||
|
||||
# Override the get_servers_1234 handler status to SUSPENDED, but
|
||||
# return the ACTIVE state first (twice, so we sleep)
|
||||
d1 = {'server': self.fc.client.get_servers_detail()[1]['servers'][0]}
|
||||
d2 = copy.deepcopy(d1)
|
||||
d1['server']['status'] = 'ACTIVE'
|
||||
|
@ -1931,6 +1928,19 @@ class ServersTest(common.HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_server_suspend_in_create_complete(self):
|
||||
self._test_server_status_suspend('test_suspend_in_create_complete')
|
||||
|
||||
def test_server_suspend_in_suspend_failed(self):
|
||||
self._test_server_status_suspend(
|
||||
name='test_suspend_in_suspend_failed',
|
||||
state=('SUSPEND', 'FAILED'))
|
||||
|
||||
def test_server_suspend_in_suspend_complete(self):
|
||||
self._test_server_status_suspend(
|
||||
name='test_suspend_in_suspend_complete',
|
||||
state=('SUSPEND', 'COMPLETE'))
|
||||
|
||||
def test_server_status_suspend_unknown_status(self):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
server = self._create_test_server(return_server,
|
||||
|
@ -1962,16 +1972,13 @@ class ServersTest(common.HeatTestCase):
|
|||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_server_status_resume(self):
|
||||
def _test_server_status_resume(self, name, state=('SUSPEND', 'COMPLETE')):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
server = self._create_test_server(return_server,
|
||||
'srv_res_w')
|
||||
server = self._create_test_server(return_server, name)
|
||||
|
||||
server.resource_id = '1234'
|
||||
self.m.ReplayAll()
|
||||
server.state_set(state[0], state[1])
|
||||
|
||||
# Override the get_servers_1234 handler status to ACTIVE, but
|
||||
# return the SUSPENDED state first (twice, so we sleep)
|
||||
d1 = {'server': self.fc.client.get_servers_detail()[1]['servers'][0]}
|
||||
d2 = copy.deepcopy(d1)
|
||||
d1['server']['status'] = 'SUSPENDED'
|
||||
|
@ -1983,13 +1990,25 @@ class ServersTest(common.HeatTestCase):
|
|||
get().AndReturn((200, d2))
|
||||
self.m.ReplayAll()
|
||||
|
||||
server.state_set(server.SUSPEND, server.COMPLETE)
|
||||
|
||||
scheduler.TaskRunner(server.resume)()
|
||||
self.assertEqual((server.RESUME, server.COMPLETE), server.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_server_resume_in_suspend_complete(self):
|
||||
self._test_server_status_resume(
|
||||
name='test_resume_in_suspend_complete')
|
||||
|
||||
def test_server_resume_in_resume_failed(self):
|
||||
self._test_server_status_resume(
|
||||
name='test_resume_in_resume_failed',
|
||||
state=('RESUME', 'FAILED'))
|
||||
|
||||
def test_server_resume_in_resume_complete(self):
|
||||
self._test_server_status_resume(
|
||||
name='test_resume_in_resume_complete',
|
||||
state=('RESUME', 'COMPLETE'))
|
||||
|
||||
def test_server_status_resume_no_resource_id(self):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
server = self._create_test_server(return_server,
|
||||
|
|
|
@ -980,7 +980,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
scheduler.TaskRunner(res.resume)()
|
||||
self.assertEqual((res.RESUME, res.COMPLETE), res.state)
|
||||
|
||||
def test_suspend_fail_inprogress(self):
|
||||
def test_suspend_fail_invalid_states(self):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_resource',
|
||||
'GenericResourceType',
|
||||
{'Foo': 'abc'})
|
||||
|
@ -988,19 +988,19 @@ class ResourceTest(common.HeatTestCase):
|
|||
scheduler.TaskRunner(res.create)()
|
||||
self.assertEqual((res.CREATE, res.COMPLETE), res.state)
|
||||
|
||||
res.state_set(res.CREATE, res.IN_PROGRESS)
|
||||
suspend = scheduler.TaskRunner(res.suspend)
|
||||
self.assertRaises(exception.ResourceFailure, suspend)
|
||||
invalid_actions = (a for a in res.ACTIONS if a != res.SUSPEND)
|
||||
invalid_status = (s for s in res.STATUSES if s != res.COMPLETE)
|
||||
invalid_states = [s for s in
|
||||
itertools.product(invalid_actions, invalid_status)]
|
||||
|
||||
res.state_set(res.UPDATE, res.IN_PROGRESS)
|
||||
suspend = scheduler.TaskRunner(res.suspend)
|
||||
self.assertRaises(exception.ResourceFailure, suspend)
|
||||
for state in invalid_states:
|
||||
res.state_set(*state)
|
||||
suspend = scheduler.TaskRunner(res.suspend)
|
||||
expected = 'State %s invalid for suspend' % six.text_type(state)
|
||||
exc = self.assertRaises(exception.ResourceFailure, suspend)
|
||||
self.assertIn(expected, six.text_type(exc))
|
||||
|
||||
res.state_set(res.DELETE, res.IN_PROGRESS)
|
||||
suspend = scheduler.TaskRunner(res.suspend)
|
||||
self.assertRaises(exception.ResourceFailure, suspend)
|
||||
|
||||
def test_resume_fail_not_suspend_complete(self):
|
||||
def test_resume_fail_invalid_states(self):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_resource',
|
||||
'GenericResourceType',
|
||||
{'Foo': 'abc'})
|
||||
|
@ -1008,13 +1008,17 @@ class ResourceTest(common.HeatTestCase):
|
|||
scheduler.TaskRunner(res.create)()
|
||||
self.assertEqual((res.CREATE, res.COMPLETE), res.state)
|
||||
|
||||
non_suspended_states = [s for s in
|
||||
itertools.product(res.ACTIONS, res.STATUSES)
|
||||
if s != (res.SUSPEND, res.COMPLETE)]
|
||||
for state in non_suspended_states:
|
||||
invalid_states = [s for s in
|
||||
itertools.product(res.ACTIONS, res.STATUSES)
|
||||
if s not in ((res.SUSPEND, res.COMPLETE),
|
||||
(res.RESUME, res.FAILED),
|
||||
(res.RESUME, res.COMPLETE))]
|
||||
for state in invalid_states:
|
||||
res.state_set(*state)
|
||||
resume = scheduler.TaskRunner(res.resume)
|
||||
self.assertRaises(exception.ResourceFailure, resume)
|
||||
expected = 'State %s invalid for resume' % six.text_type(state)
|
||||
exc = self.assertRaises(exception.ResourceFailure, resume)
|
||||
self.assertIn(expected, six.text_type(exc))
|
||||
|
||||
def test_suspend_fail_exception(self):
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_resource',
|
||||
|
|
Loading…
Reference in New Issue