Revert "Move deployment handle_signal to rpc call"
This reverts commit a63f634bfb
.
This commit caused a regression in tripleo-ci whith a database
"Incorrect datetime value" error.
Change-Id: I55f9be8ffb319edb56371d8d370d58d02bdf3867
Closes-Bug: #1423126
This commit is contained in:
parent
6ae39a4699
commit
b387a9f27a
|
@ -14,8 +14,8 @@
|
|||
import copy
|
||||
import uuid
|
||||
|
||||
from oslo.utils import timeutils
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
|
@ -448,9 +448,58 @@ class SoftwareDeployment(signal_responder.SignalResponder):
|
|||
return self._check_complete()
|
||||
|
||||
def handle_signal(self, details):
|
||||
return self.rpc_client().signal_software_deployment(
|
||||
self.context, self.resource_id, details,
|
||||
timeutils.strtime())
|
||||
sd = self.rpc_client().show_software_deployment(
|
||||
self.context, self.resource_id)
|
||||
sc = self.rpc_client().show_software_config(
|
||||
self.context, self.properties[self.CONFIG])
|
||||
status = sd[rpc_api.SOFTWARE_DEPLOYMENT_STATUS]
|
||||
|
||||
if not status == self.IN_PROGRESS:
|
||||
# output values are only expected when in an IN_PROGRESS state
|
||||
return
|
||||
|
||||
details = details or {}
|
||||
|
||||
ov = sd[rpc_api.SOFTWARE_DEPLOYMENT_OUTPUT_VALUES] or {}
|
||||
status = None
|
||||
status_reasons = {}
|
||||
status_code = details.get(self.STATUS_CODE)
|
||||
if status_code and str(status_code) != '0':
|
||||
status = self.FAILED
|
||||
status_reasons[self.STATUS_CODE] = _(
|
||||
'Deployment exited with non-zero status code: %s'
|
||||
) % details.get(self.STATUS_CODE)
|
||||
event_reason = 'deployment failed (%s)' % status_code
|
||||
else:
|
||||
event_reason = 'deployment succeeded'
|
||||
|
||||
for output in sc[rpc_api.SOFTWARE_CONFIG_OUTPUTS] or []:
|
||||
out_key = output['name']
|
||||
if out_key in details:
|
||||
ov[out_key] = details[out_key]
|
||||
if output.get('error_output', False):
|
||||
status = self.FAILED
|
||||
status_reasons[out_key] = details[out_key]
|
||||
event_reason = 'deployment failed'
|
||||
|
||||
for out_key in self.ATTRIBUTES:
|
||||
ov[out_key] = details.get(out_key)
|
||||
|
||||
if status == self.FAILED:
|
||||
# build a status reason out of all of the values of outputs
|
||||
# flagged as error_output
|
||||
status_reasons = [' : '.join((k, six.text_type(status_reasons[k])))
|
||||
for k in status_reasons]
|
||||
status_reason = ', '.join(status_reasons)
|
||||
else:
|
||||
status = self.COMPLETE
|
||||
status_reason = _('Outputs received')
|
||||
|
||||
self.rpc_client().update_software_deployment(
|
||||
self.context, deployment_id=self.resource_id,
|
||||
output_values=ov, status=status, status_reason=status_reason)
|
||||
# Return a string describing the outcome of handling the signal data
|
||||
return event_reason
|
||||
|
||||
def FnGetAtt(self, key, *path):
|
||||
'''
|
||||
|
|
|
@ -1477,66 +1477,6 @@ class EngineService(service.Service):
|
|||
self._push_metadata_software_deployments(cnxt, server_id)
|
||||
return api.format_software_deployment(sd)
|
||||
|
||||
@request_context
|
||||
def signal_software_deployment(self, cnxt, deployment_id, details,
|
||||
updated_at):
|
||||
|
||||
if not deployment_id:
|
||||
raise ValueError(_('deployment_id must be specified'))
|
||||
|
||||
sd = db_api.software_deployment_get(cnxt, deployment_id)
|
||||
status = sd.status
|
||||
|
||||
if not status == rpc_api.SOFTWARE_DEPLOYMENT_IN_PROGRESS:
|
||||
# output values are only expected when in an IN_PROGRESS state
|
||||
return
|
||||
|
||||
details = details or {}
|
||||
|
||||
output_status_code = rpc_api.SOFTWARE_DEPLOYMENT_OUTPUT_STATUS_CODE
|
||||
ov = sd.output_values or {}
|
||||
status = None
|
||||
status_reasons = {}
|
||||
status_code = details.get(output_status_code)
|
||||
if status_code and str(status_code) != '0':
|
||||
status = rpc_api.SOFTWARE_DEPLOYMENT_FAILED
|
||||
status_reasons[output_status_code] = _(
|
||||
'Deployment exited with non-zero status code: %s'
|
||||
) % details.get(output_status_code)
|
||||
event_reason = 'deployment failed (%s)' % status_code
|
||||
else:
|
||||
event_reason = 'deployment succeeded'
|
||||
|
||||
for output in sd.config.config['outputs'] or []:
|
||||
out_key = output['name']
|
||||
if out_key in details:
|
||||
ov[out_key] = details[out_key]
|
||||
if output.get('error_output', False):
|
||||
status = rpc_api.SOFTWARE_DEPLOYMENT_FAILED
|
||||
status_reasons[out_key] = details[out_key]
|
||||
event_reason = 'deployment failed'
|
||||
|
||||
for out_key in rpc_api.SOFTWARE_DEPLOYMENT_OUTPUTS:
|
||||
ov[out_key] = details.get(out_key)
|
||||
|
||||
if status == rpc_api.SOFTWARE_DEPLOYMENT_FAILED:
|
||||
# build a status reason out of all of the values of outputs
|
||||
# flagged as error_output
|
||||
status_reasons = [' : '.join((k, six.text_type(status_reasons[k])))
|
||||
for k in status_reasons]
|
||||
status_reason = ', '.join(status_reasons)
|
||||
else:
|
||||
status = rpc_api.SOFTWARE_DEPLOYMENT_COMPLETE
|
||||
status_reason = _('Outputs received')
|
||||
|
||||
self.update_software_deployment(
|
||||
cnxt, deployment_id=deployment_id,
|
||||
output_values=ov, status=status, status_reason=status_reason,
|
||||
config_id=None, input_values=None, action=None,
|
||||
updated_at=updated_at)
|
||||
# Return a string describing the outcome of handling the signal data
|
||||
return event_reason
|
||||
|
||||
@request_context
|
||||
def update_software_deployment(self, cnxt, deployment_id, config_id,
|
||||
input_values, output_values, action,
|
||||
|
|
|
@ -235,26 +235,6 @@ SOFTWARE_DEPLOYMENT_KEYS = (
|
|||
'updated_time'
|
||||
)
|
||||
|
||||
SOFTWARE_DEPLOYMENT_STATUSES = (
|
||||
SOFTWARE_DEPLOYMENT_IN_PROGRESS,
|
||||
SOFTWARE_DEPLOYMENT_FAILED,
|
||||
SOFTWARE_DEPLOYMENT_COMPLETE
|
||||
) = (
|
||||
'IN_PROGRESS',
|
||||
'FAILED',
|
||||
'COMPLETE'
|
||||
)
|
||||
|
||||
SOFTWARE_DEPLOYMENT_OUTPUTS = (
|
||||
SOFTWARE_DEPLOYMENT_OUTPUT_STDOUT,
|
||||
SOFTWARE_DEPLOYMENT_OUTPUT_STDERR,
|
||||
SOFTWARE_DEPLOYMENT_OUTPUT_STATUS_CODE
|
||||
) = (
|
||||
'deploy_stdout',
|
||||
'deploy_stderr',
|
||||
'deploy_status_code'
|
||||
)
|
||||
|
||||
SNAPSHOT_KEYS = (
|
||||
SNAPSHOT_ID,
|
||||
SNAPSHOT_NAME,
|
||||
|
|
|
@ -546,15 +546,6 @@ class EngineClient(object):
|
|||
return self.call(cnxt, self.make_msg('delete_software_deployment',
|
||||
deployment_id=deployment_id))
|
||||
|
||||
def signal_software_deployment(self, cnxt, deployment_id, details,
|
||||
updated_at=None):
|
||||
return self.call(
|
||||
cnxt, self.make_msg('signal_software_deployment',
|
||||
deployment_id=deployment_id,
|
||||
details=details,
|
||||
updated_at=updated_at),
|
||||
version='1.5')
|
||||
|
||||
def stack_snapshot(self, ctxt, stack_identity, name):
|
||||
return self.call(ctxt, self.make_msg('stack_snapshot',
|
||||
stack_identity=stack_identity,
|
||||
|
|
|
@ -3387,125 +3387,6 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
|
|||
deployment,
|
||||
self.engine.show_software_deployment(self.ctx, deployment_id))
|
||||
|
||||
@mock.patch.object(service.EngineService,
|
||||
'_push_metadata_software_deployments')
|
||||
def test_signal_software_deployment(self, pmsd):
|
||||
self.assertRaises(ValueError,
|
||||
self.engine.signal_software_deployment,
|
||||
self.ctx, None, {}, None)
|
||||
deployment_id = str(uuid.uuid4())
|
||||
ex = self.assertRaises(dispatcher.ExpectedException,
|
||||
self.engine.signal_software_deployment,
|
||||
self.ctx, deployment_id, {}, None)
|
||||
self.assertEqual(exception.NotFound, ex.exc_info[0])
|
||||
|
||||
deployment = self._create_software_deployment()
|
||||
deployment_id = deployment['id']
|
||||
|
||||
# signal is ignore unless deployment is IN_PROGRESS
|
||||
self.assertIsNone(self.engine.signal_software_deployment(
|
||||
self.ctx, deployment_id, {}, None))
|
||||
|
||||
# simple signal, no data
|
||||
deployment = self._create_software_deployment(
|
||||
action='INIT', status='IN_PROGRESS')
|
||||
deployment_id = deployment['id']
|
||||
self.assertEqual(
|
||||
'deployment succeeded',
|
||||
self.engine.signal_software_deployment(
|
||||
self.ctx, deployment_id, {}, None))
|
||||
sd = db_api.software_deployment_get(self.ctx, deployment_id)
|
||||
self.assertEqual('COMPLETE', sd.status)
|
||||
self.assertEqual('Outputs received', sd.status_reason)
|
||||
self.assertEqual({
|
||||
'deploy_status_code': None,
|
||||
'deploy_stderr': None,
|
||||
'deploy_stdout': None
|
||||
}, sd.output_values)
|
||||
self.assertIsNotNone(sd.updated_at)
|
||||
|
||||
# simple signal, some data
|
||||
config = self._create_software_config(outputs=[{'name': 'foo'}])
|
||||
deployment = self._create_software_deployment(
|
||||
config_id=config['id'], action='INIT', status='IN_PROGRESS')
|
||||
deployment_id = deployment['id']
|
||||
result = self.engine.signal_software_deployment(
|
||||
self.ctx,
|
||||
deployment_id,
|
||||
{'foo': 'bar', 'deploy_status_code': 0},
|
||||
None)
|
||||
self.assertEqual('deployment succeeded', result)
|
||||
sd = db_api.software_deployment_get(self.ctx, deployment_id)
|
||||
self.assertEqual('COMPLETE', sd.status)
|
||||
self.assertEqual('Outputs received', sd.status_reason)
|
||||
self.assertEqual({
|
||||
'deploy_status_code': 0,
|
||||
'foo': 'bar',
|
||||
'deploy_stderr': None,
|
||||
'deploy_stdout': None
|
||||
}, sd.output_values)
|
||||
self.assertIsNotNone(sd.updated_at)
|
||||
|
||||
# failed signal on deploy_status_code
|
||||
config = self._create_software_config(outputs=[
|
||||
{'name': 'foo'}])
|
||||
deployment = self._create_software_deployment(
|
||||
config_id=config['id'], action='INIT', status='IN_PROGRESS')
|
||||
deployment_id = deployment['id']
|
||||
result = self.engine.signal_software_deployment(
|
||||
self.ctx,
|
||||
deployment_id,
|
||||
{
|
||||
'foo': 'bar',
|
||||
'deploy_status_code': -1,
|
||||
'deploy_stderr': 'Its gone Pete Tong'
|
||||
},
|
||||
None)
|
||||
self.assertEqual('deployment failed (-1)', result)
|
||||
sd = db_api.software_deployment_get(self.ctx, deployment_id)
|
||||
self.assertEqual('FAILED', sd.status)
|
||||
self.assertEqual(
|
||||
('deploy_status_code : Deployment exited with non-zero '
|
||||
'status code: -1'),
|
||||
sd.status_reason)
|
||||
self.assertEqual({
|
||||
'deploy_status_code': -1,
|
||||
'foo': 'bar',
|
||||
'deploy_stderr': 'Its gone Pete Tong',
|
||||
'deploy_stdout': None
|
||||
}, sd.output_values)
|
||||
self.assertIsNotNone(sd.updated_at)
|
||||
|
||||
# failed signal on error_output foo
|
||||
config = self._create_software_config(outputs=[
|
||||
{'name': 'foo', 'error_output': True}])
|
||||
deployment = self._create_software_deployment(
|
||||
config_id=config['id'], action='INIT', status='IN_PROGRESS')
|
||||
deployment_id = deployment['id']
|
||||
result = self.engine.signal_software_deployment(
|
||||
self.ctx,
|
||||
deployment_id,
|
||||
{
|
||||
'foo': 'bar',
|
||||
'deploy_status_code': -1,
|
||||
'deploy_stderr': 'Its gone Pete Tong'
|
||||
},
|
||||
None)
|
||||
self.assertEqual('deployment failed', result)
|
||||
sd = db_api.software_deployment_get(self.ctx, deployment_id)
|
||||
self.assertEqual('FAILED', sd.status)
|
||||
self.assertEqual(
|
||||
('foo : bar, deploy_status_code : Deployment exited with '
|
||||
'non-zero status code: -1'),
|
||||
sd.status_reason)
|
||||
self.assertEqual({
|
||||
'deploy_status_code': -1,
|
||||
'foo': 'bar',
|
||||
'deploy_stderr': 'Its gone Pete Tong',
|
||||
'deploy_stdout': None
|
||||
}, sd.output_values)
|
||||
self.assertIsNotNone(sd.updated_at)
|
||||
|
||||
def test_create_software_deployment(self):
|
||||
kwargs = {
|
||||
'group': 'Heat::Chef',
|
||||
|
|
|
@ -641,91 +641,155 @@ class SoftwareDeploymentTest(common.HeatTestCase):
|
|||
def test_handle_signal_ok_zero(self):
|
||||
self._create_stack(self.template)
|
||||
self.deployment.resource_id = 'c8a19429-7fde-47ea-a42f-40045488226c'
|
||||
rpcc = self.rpc_client
|
||||
rpcc.signal_software_deployment.return_value = 'deployment succeeded'
|
||||
sc = {
|
||||
'outputs': [
|
||||
{'name': 'foo'},
|
||||
{'name': 'foo2'},
|
||||
{'name': 'failed', 'error_output': True}
|
||||
]
|
||||
}
|
||||
sd = {
|
||||
'output_values': {},
|
||||
'status': self.deployment.IN_PROGRESS
|
||||
}
|
||||
self.rpc_client.show_software_deployment.return_value = sd
|
||||
self.rpc_client.show_software_config.return_value = sc
|
||||
details = {
|
||||
'foo': 'bar',
|
||||
'deploy_status_code': 0
|
||||
}
|
||||
ret = self.deployment.handle_signal(details)
|
||||
self.assertEqual('deployment succeeded', ret)
|
||||
ca = rpcc.signal_software_deployment.call_args[0]
|
||||
self.assertEqual(self.ctx, ca[0])
|
||||
self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c', ca[1])
|
||||
self.assertEqual({'foo': 'bar', 'deploy_status_code': 0}, ca[2])
|
||||
self.assertIsNotNone(ca[3])
|
||||
self.assertEqual({
|
||||
'deployment_id': 'c8a19429-7fde-47ea-a42f-40045488226c',
|
||||
'output_values': {
|
||||
'foo': 'bar',
|
||||
'deploy_status_code': 0,
|
||||
'deploy_stderr': None,
|
||||
'deploy_stdout': None
|
||||
},
|
||||
'status': 'COMPLETE',
|
||||
'status_reason': 'Outputs received'},
|
||||
self.rpc_client.update_software_deployment.call_args[1])
|
||||
|
||||
def test_handle_signal_ok_str_zero(self):
|
||||
self._create_stack(self.template)
|
||||
self.deployment.resource_id = 'c8a19429-7fde-47ea-a42f-40045488226c'
|
||||
rpcc = self.rpc_client
|
||||
rpcc.signal_software_deployment.return_value = 'deployment succeeded'
|
||||
sc = {
|
||||
'outputs': [
|
||||
{'name': 'foo'},
|
||||
{'name': 'foo2'},
|
||||
{'name': 'failed', 'error_output': True}
|
||||
]
|
||||
}
|
||||
sd = {
|
||||
'output_values': {},
|
||||
'status': self.deployment.IN_PROGRESS
|
||||
}
|
||||
self.rpc_client.show_software_deployment.return_value = sd
|
||||
self.rpc_client.show_software_config.return_value = sc
|
||||
details = {
|
||||
'foo': 'bar',
|
||||
'deploy_status_code': '0'
|
||||
}
|
||||
ret = self.deployment.handle_signal(details)
|
||||
self.assertEqual('deployment succeeded', ret)
|
||||
ca = rpcc.signal_software_deployment.call_args[0]
|
||||
self.assertEqual(self.ctx, ca[0])
|
||||
self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c', ca[1])
|
||||
self.assertEqual({'foo': 'bar', 'deploy_status_code': '0'}, ca[2])
|
||||
self.assertIsNotNone(ca[3])
|
||||
self.assertEqual({
|
||||
'deployment_id': 'c8a19429-7fde-47ea-a42f-40045488226c',
|
||||
'output_values': {
|
||||
'foo': 'bar',
|
||||
'deploy_status_code': '0',
|
||||
'deploy_stderr': None,
|
||||
'deploy_stdout': None
|
||||
},
|
||||
'status': 'COMPLETE',
|
||||
'status_reason': 'Outputs received'},
|
||||
self.rpc_client.update_software_deployment.call_args[1])
|
||||
|
||||
def test_handle_signal_failed(self):
|
||||
self._create_stack(self.template)
|
||||
self.deployment.resource_id = 'c8a19429-7fde-47ea-a42f-40045488226c'
|
||||
rpcc = self.rpc_client
|
||||
rpcc.signal_software_deployment.return_value = 'deployment failed'
|
||||
|
||||
sc = {
|
||||
'outputs': [
|
||||
{'name': 'foo'},
|
||||
{'name': 'foo2'},
|
||||
{'name': 'failed', 'error_output': True}
|
||||
]
|
||||
}
|
||||
sd = {
|
||||
'output_values': {},
|
||||
'status': self.deployment.IN_PROGRESS
|
||||
}
|
||||
self.rpc_client.show_software_deployment.return_value = sd
|
||||
self.rpc_client.show_software_config.return_value = sc
|
||||
details = {'failed': 'no enough memory found.'}
|
||||
ret = self.deployment.handle_signal(details)
|
||||
self.assertEqual('deployment failed', ret)
|
||||
ca = rpcc.signal_software_deployment.call_args[0]
|
||||
self.assertEqual(self.ctx, ca[0])
|
||||
self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c', ca[1])
|
||||
self.assertEqual(details, ca[2])
|
||||
self.assertIsNotNone(ca[3])
|
||||
self.assertEqual({
|
||||
'deployment_id': 'c8a19429-7fde-47ea-a42f-40045488226c',
|
||||
'output_values': {
|
||||
'deploy_status_code': None,
|
||||
'deploy_stderr': None,
|
||||
'deploy_stdout': None,
|
||||
'failed': 'no enough memory found.'
|
||||
},
|
||||
'status': 'FAILED',
|
||||
'status_reason': 'failed : no enough memory found.'},
|
||||
self.rpc_client.update_software_deployment.call_args[1])
|
||||
|
||||
# Test bug 1332355, where details contains a translateable message
|
||||
details = {'failed': _('need more memory.')}
|
||||
ret = self.deployment.handle_signal(details)
|
||||
self.assertEqual('deployment failed', ret)
|
||||
ca = rpcc.signal_software_deployment.call_args[0]
|
||||
self.assertEqual(self.ctx, ca[0])
|
||||
self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c', ca[1])
|
||||
self.assertEqual(details, ca[2])
|
||||
self.assertIsNotNone(ca[3])
|
||||
self.deployment.handle_signal(details)
|
||||
self.assertEqual({
|
||||
'deployment_id': 'c8a19429-7fde-47ea-a42f-40045488226c',
|
||||
'output_values': {
|
||||
'deploy_status_code': None,
|
||||
'deploy_stderr': None,
|
||||
'deploy_stdout': None,
|
||||
'failed': 'need more memory.'
|
||||
},
|
||||
'status': 'FAILED',
|
||||
'status_reason': 'failed : need more memory.'},
|
||||
self.rpc_client.update_software_deployment.call_args[1])
|
||||
|
||||
def test_handle_status_code_failed(self):
|
||||
self._create_stack(self.template)
|
||||
self.deployment.resource_id = 'c8a19429-7fde-47ea-a42f-40045488226c'
|
||||
rpcc = self.rpc_client
|
||||
rpcc.signal_software_deployment.return_value = 'deployment failed'
|
||||
|
||||
sd = {
|
||||
'outputs': [],
|
||||
'output_values': {},
|
||||
'status': self.deployment.IN_PROGRESS
|
||||
}
|
||||
self.rpc_client.show_software_deployment.return_value = sd
|
||||
details = {
|
||||
'deploy_stdout': 'A thing happened',
|
||||
'deploy_stderr': 'Then it broke',
|
||||
'deploy_status_code': -1
|
||||
}
|
||||
self.deployment.handle_signal(details)
|
||||
ca = rpcc.signal_software_deployment.call_args[0]
|
||||
self.assertEqual(self.ctx, ca[0])
|
||||
self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c', ca[1])
|
||||
self.assertEqual(details, ca[2])
|
||||
self.assertIsNotNone(ca[3])
|
||||
self.assertEqual(
|
||||
'c8a19429-7fde-47ea-a42f-40045488226c',
|
||||
self.rpc_client.show_software_deployment.call_args[0][1])
|
||||
self.assertEqual({
|
||||
'deployment_id': 'c8a19429-7fde-47ea-a42f-40045488226c',
|
||||
'output_values': {
|
||||
'deploy_stdout': 'A thing happened',
|
||||
'deploy_stderr': 'Then it broke',
|
||||
'deploy_status_code': -1
|
||||
},
|
||||
'status': 'FAILED',
|
||||
'status_reason': ('deploy_status_code : Deployment exited '
|
||||
'with non-zero status code: -1')},
|
||||
self.rpc_client.update_software_deployment.call_args[1])
|
||||
|
||||
def test_handle_signal_not_waiting(self):
|
||||
self._create_stack(self.template)
|
||||
rpcc = self.rpc_client
|
||||
rpcc.signal_software_deployment.return_value = None
|
||||
sd = {
|
||||
'status': self.deployment.COMPLETE
|
||||
}
|
||||
self.rpc_client.show_software_deployment.return_value = sd
|
||||
details = None
|
||||
self.assertIsNone(self.deployment.handle_signal(details))
|
||||
ca = rpcc.signal_software_deployment.call_args[0]
|
||||
self.assertEqual(self.ctx, ca[0])
|
||||
self.assertIsNone(ca[1])
|
||||
self.assertIsNone(ca[2])
|
||||
self.assertIsNotNone(ca[3])
|
||||
|
||||
def test_fn_get_att(self):
|
||||
self._create_stack(self.template)
|
||||
|
|
Loading…
Reference in New Issue