From fc676986b755bfeaae4f1e87e79e048e1ab771f4 Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Fri, 11 Jul 2014 20:48:45 +0100 Subject: [PATCH] Allow plugins to specify signal event reason Currently, we have logic in the Resource.signal base-class implementation which works out the reason string based on knowledge of some of the signal-handling resources. This is invariably going to be fragile, and it won't work at all with any out of tree or contrib plugins. So instead, move towards a model where we accept an optional return value from handle_signal, and use that as the reason string instead. Since no resources yet return a reason, maintain the old logic as a fallback path, until this gets migrated into the appropriate resources. Change-Id: I45fdf112e6cd050bb1f4111977f653ba6440df02 Partial-Bug: #1340894 --- heat/engine/resource.py | 8 ++++++-- heat/tests/test_signal.py | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 511e430b1f..0f298ccbe9 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -897,8 +897,12 @@ class Resource(object): str(self)) raise Exception(msg) - self._add_event('signal', self.status, get_string_details()) - self.handle_signal(details) + signal_result = self.handle_signal(details) + if signal_result: + reason_string = "Signal: %s" % signal_result + else: + reason_string = get_string_details() + self._add_event('signal', self.status, reason_string) except Exception as ex: LOG.exception(_('signal %(name)s : %(msg)s') % {'name': str(self), 'msg': ex}) diff --git a/heat/tests/test_signal.py b/heat/tests/test_signal.py index e5acea4435..68122a665a 100644 --- a/heat/tests/test_signal.py +++ b/heat/tests/test_signal.py @@ -297,6 +297,30 @@ class SignalTest(HeatTestCase): self.m.VerifyAll() + def test_signal_plugin_reason(self): + # Ensure if handle_signal returns data, we use it as the reason + self.stack = self.create_stack() + self.stack.create() + + rsrc = self.stack['signal_handler'] + self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state) + + self.m.StubOutWithMock(generic_resource.SignalResource, + 'handle_signal') + signal_details = {'status': 'COMPLETE'} + ret_expected = "Received COMPLETE signal" + generic_resource.SignalResource.handle_signal( + signal_details).AndReturn(ret_expected) + + self.m.StubOutWithMock(generic_resource.SignalResource, + '_add_event') + generic_resource.SignalResource._add_event( + 'signal', 'COMPLETE', 'Signal: %s' % ret_expected).AndReturn(None) + self.m.ReplayAll() + + rsrc.signal(details=signal_details) + self.m.VerifyAll() + def test_signal_wrong_resource(self): # assert that we get the correct exception when calling a # resource.signal() that does not have a handle_signal()