diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-02-25 13:47:52 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-02-25 13:47:52 +0000 |
commit | 7887beafe6cf3edd016f6753ff23181ac9c6cf0e (patch) | |
tree | 8be8b2734a3c9367716d989aaff5e11ecc54f71c | |
parent | 06b2ef0e3ccd0e224c85b6d49a1ff7aa475c581d (diff) | |
parent | 302040c759e13ac93c9bf8a6b1acd14c73faaad7 (diff) | |
download | python-heatclient-7887beafe6cf3edd016f6753ff23181ac9c6cf0e.tar.gz |
Merge "Move poll_for_events to event_utils"
-rw-r--r-- | heatclient/common/event_utils.py | 30 | ||||
-rw-r--r-- | heatclient/tests/unit/test_event_utils.py | 65 | ||||
-rw-r--r-- | heatclient/v1/shell.py | 47 |
3 files changed, 104 insertions, 38 deletions
diff --git a/heatclient/common/event_utils.py b/heatclient/common/event_utils.py index 27685f0..03bb8b2 100644 --- a/heatclient/common/event_utils.py +++ b/heatclient/common/event_utils.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import time + from heatclient.common import utils import heatclient.exc as exc @@ -126,3 +128,31 @@ def _get_stack_events(hc, stack_id, event_args): for e in events: e.stack_name = stack_id.split("/")[0] return events + + +def poll_for_events(hc, stack_name, action, poll_period): + """Continuously poll events and logs for performed action on stack.""" + + marker = None + stop_status = ('%s_FAILED' % action, '%s_COMPLETE' % action) + while True: + events = get_events(hc, stack_id=stack_name, + event_args={'sort_dir': 'asc', + 'marker': marker}) + + if len(events) >= 1: + # set marker to last event that was received. + marker = getattr(events[-1], 'id', None) + events_log = utils.event_log_formatter(events) + print(events_log) + + for event in events: + # check if stack event was also received + if getattr(event, 'resource_name', '') == stack_name: + stack_status = getattr(event, 'resource_status', '') + msg = _("\n Stack %(name)s %(status)s \n") % dict( + name=stack_name, status=stack_status) + if stack_status in stop_status: + return stack_status, msg + + time.sleep(poll_period) diff --git a/heatclient/tests/unit/test_event_utils.py b/heatclient/tests/unit/test_event_utils.py index bba77b4..d2350e5 100644 --- a/heatclient/tests/unit/test_event_utils.py +++ b/heatclient/tests/unit/test_event_utils.py @@ -36,11 +36,13 @@ class ShellTestEventUtils(testtools.TestCase): return hc_res.Resource(manager=None, info=res_info) @staticmethod - def _mock_event(event_id, resource_id): + def _mock_event(event_id, resource_id, + resource_status='CREATE_COMPLETE'): ev_info = {"links": [{"href": "http://heat/foo", "rel": "self"}], "logical_resource_id": resource_id, "physical_resource_id": resource_id, - "resource_status": "CREATE_COMPLETE", + "resource_name": resource_id, + "resource_status": resource_status, "resource_status_reason": "state changed", "event_time": "2014-12-05T14:14:30Z", "id": event_id} @@ -128,3 +130,62 @@ class ShellTestEventUtils(testtools.TestCase): self.assertEqual('event1', evs[0].id) self.assertEqual('event2', evs[1].id) self.assertEqual('event3', evs[2].id) + + @mock.patch('heatclient.common.event_utils.get_events') + def test_poll_for_events(self, ge): + ge.side_effect = [[ + self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'), + self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'), + self._mock_event('3', 'res_child2', 'CREATE_IN_PROGRESS'), + self._mock_event('4', 'res_child3', 'CREATE_IN_PROGRESS') + ], [ + self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'), + self._mock_event('6', 'res_child2', 'CREATE_COMPLETE'), + self._mock_event('7', 'res_child3', 'CREATE_COMPLETE'), + self._mock_event('8', 'astack', 'CREATE_COMPLETE') + ]] + + stack_status, msg = event_utils.poll_for_events( + None, 'astack', 'CREATE', 0) + self.assertEqual('CREATE_COMPLETE', stack_status) + self.assertEqual('\n Stack astack CREATE_COMPLETE \n', msg) + ge.assert_has_calls([ + mock.call(None, stack_id='astack', event_args={ + 'sort_dir': 'asc', 'marker': None + }), + mock.call(None, stack_id='astack', event_args={ + 'sort_dir': 'asc', 'marker': '4' + }) + ]) + + @mock.patch('heatclient.common.event_utils.get_events') + def test_poll_for_events_in_progress_resource(self, ge): + ge.side_effect = [[ + self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'), + self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'), + self._mock_event('3', 'astack', 'CREATE_COMPLETE') + ]] + + stack_status, msg = event_utils.poll_for_events( + None, 'astack', 'CREATE', 0) + self.assertEqual('CREATE_COMPLETE', stack_status) + self.assertEqual('\n Stack astack CREATE_COMPLETE \n', msg) + + @mock.patch('heatclient.common.event_utils.get_events') + def test_poll_for_events_failed(self, ge): + ge.side_effect = [[ + self._mock_event('1', 'astack', 'CREATE_IN_PROGRESS'), + self._mock_event('2', 'res_child1', 'CREATE_IN_PROGRESS'), + self._mock_event('3', 'res_child2', 'CREATE_IN_PROGRESS'), + self._mock_event('4', 'res_child3', 'CREATE_IN_PROGRESS') + ], [ + self._mock_event('5', 'res_child1', 'CREATE_COMPLETE'), + self._mock_event('6', 'res_child2', 'CREATE_FAILED'), + self._mock_event('7', 'res_child3', 'CREATE_COMPLETE'), + self._mock_event('8', 'astack', 'CREATE_FAILED') + ]] + + stack_status, msg = event_utils.poll_for_events( + None, 'astack', 'CREATE', 0) + self.assertEqual('CREATE_FAILED', stack_status) + self.assertEqual('\n Stack astack CREATE_FAILED \n', msg) diff --git a/heatclient/v1/shell.py b/heatclient/v1/shell.py index 1c613af..d530958 100644 --- a/heatclient/v1/shell.py +++ b/heatclient/v1/shell.py @@ -19,7 +19,6 @@ from oslo_serialization import jsonutils from oslo_utils import strutils import six from six.moves.urllib import request -import time import yaml from heatclient.common import deployment_utils @@ -137,8 +136,17 @@ def do_stack_create(hc, args): hc.stacks.create(**fields) do_stack_list(hc) - if args.poll is not None: - _poll_for_events(hc, args.name, 'CREATE', args.poll) + if not args.poll: + return + + show_fields = {'stack_id': args.name} + _do_stack_show(hc, show_fields) + stack_status, msg = event_utils.poll_for_events( + hc, args.name, action='CREATE', poll_period=args.poll) + _do_stack_show(hc, show_fields) + if stack_status == 'CREATE_FAILED': + raise exc.StackFailure(msg) + print(msg) @utils.arg('-e', '--environment-file', metavar='<FILE or URL>', @@ -1557,36 +1565,3 @@ def _do_stack_show(hc, fields): 'tags': utils.json_formatter } utils.print_dict(stack.to_dict(), formatters=formatters) - - -def _poll_for_events(hc, stack_name, action, poll_period): - """Continuously poll events and logs for performed action on stack.""" - - fields = {'stack_id': stack_name} - _do_stack_show(hc, fields) - marker = None - while True: - events = event_utils.get_events(hc, stack_id=stack_name, - event_args={'sort_dir': 'asc', - 'marker': marker}) - - if len(events) >= 1: - # set marker to last event that was received. - marker = getattr(events[-1], 'id', None) - events_log = utils.event_log_formatter(events) - print(events_log) - for event in events: - # check if stack event was also received - if getattr(event, 'resource_name', '') == stack_name: - stack_status = getattr(event, 'resource_status', '') - msg = _("\n Stack %(name)s %(status)s \n") % dict( - name=stack_name, status=stack_status) - if stack_status == '%s_COMPLETE' % action: - _do_stack_show(hc, fields) - print(msg) - return - elif stack_status == '%s_FAILED' % action: - _do_stack_show(hc, fields) - raise exc.StackFailure(msg) - - time.sleep(poll_period) |