diff options
| author | Steve Baker <sbaker@redhat.com> | 2016-02-15 13:12:19 +1300 |
|---|---|---|
| committer | Sergey Kraynev <skraynev@mirantis.com> | 2016-02-26 09:51:55 -0500 |
| commit | d00903ad9389a45ede398663f7c18337bbbda4d8 (patch) | |
| tree | 65c9d56151d640d8c87755aa6b181baf8e689ae3 | |
| parent | 0a7f8bf1d6c802db673c0956f30a41b29626196f (diff) | |
| download | python-heatclient-d00903ad9389a45ede398663f7c18337bbbda4d8.tar.gz | |
Use poll_for_events for "openstack stack <action>"
These are treated like the poll_for_events for stack update, except for
the cancel action which stops polling on any COMPLETE or FAILED state.
Change-Id: I3723bde4f26abb12674d15df65764fb6d8a67a56
Blueprint: heat-support-python-openstackclient
| -rw-r--r-- | heatclient/osc/v1/stack.py | 48 | ||||
| -rw-r--r-- | heatclient/tests/unit/osc/v1/test_stack.py | 35 |
2 files changed, 50 insertions, 33 deletions
diff --git a/heatclient/osc/v1/stack.py b/heatclient/osc/v1/stack.py index 83d4aa2..2e16a19 100644 --- a/heatclient/osc/v1/stack.py +++ b/heatclient/osc/v1/stack.py @@ -940,19 +940,18 @@ class StackActionBase(lister.Lister): ) return parser - def _take_action(self, parsed_args, action, good_status, bad_status): + def _take_action(self, parsed_args, action, action_name=None): self.log.debug("take_action(%s)", parsed_args) heat_client = self.app.client_manager.orchestration return _stacks_action( parsed_args, heat_client, action, - good_status, - bad_status + action_name ) -def _stacks_action(parsed_args, heat_client, action, good_status, bad_status): +def _stacks_action(parsed_args, heat_client, action, action_name=None): rows = [] columns = [ 'ID', @@ -963,13 +962,20 @@ def _stacks_action(parsed_args, heat_client, action, good_status, bad_status): ] for stack in parsed_args.stack: data = _stack_action(stack, parsed_args, heat_client, action, - good_status, bad_status) + action_name) rows += [utils.get_dict_properties(data.to_dict(), columns)] return (columns, rows) -def _stack_action(stack, parsed_args, heat_client, action, - good_status, bad_status): +def _stack_action(stack, parsed_args, heat_client, action, action_name=None): + if parsed_args.wait: + # find the last event to use as the marker + events = event_utils.get_events(heat_client, + stack_id=stack, + event_args={'sort_dir': 'desc', + 'limit': 1}) + marker = events[0].id if events else None + try: action(stack) except heat_exc.HTTPNotFound: @@ -977,12 +983,15 @@ def _stack_action(stack, parsed_args, heat_client, action, raise exc.CommandError(msg) if parsed_args.wait: - if not utils.wait_for_status(heat_client.stacks.get, stack, - status_field='stack_status', - success_status=good_status, - error_status=bad_status): - err = _("Error waiting for status from stack %s") % stack - raise exc.CommandError(err) + s = heat_client.stacks.get(stack) + stack_status, msg = event_utils.poll_for_events( + heat_client, s.stack_name, action=action_name, marker=marker) + if action_name: + if stack_status == '%s_FAILED' % action_name: + raise exc.CommandError(msg) + else: + if stack_status.endswith('_FAILED'): + raise exc.CommandError(msg) return heat_client.stacks.get(stack) @@ -1003,8 +1012,7 @@ class SuspendStack(StackActionBase): return self._take_action( parsed_args, self.app.client_manager.orchestration.actions.suspend, - ['suspend_complete'], - ['suspend_failed'] + 'SUSPEND' ) @@ -1024,8 +1032,7 @@ class ResumeStack(StackActionBase): return self._take_action( parsed_args, self.app.client_manager.orchestration.actions.resume, - ['resume_complete'], - ['resume_failed'] + 'RESUME' ) @@ -1045,8 +1052,7 @@ class CheckStack(StackActionBase): return self._take_action( parsed_args, self.app.client_manager.orchestration.actions.check, - ['check_complete'], - ['check_failed'] + 'CHECK' ) @@ -1090,9 +1096,7 @@ class CancelStack(StackActionBase): stack, parsed_args, heat_client, - heat_client.actions.cancel_update, - ['cancel_update_complete'], - ['cancel_update_failed'] + heat_client.actions.cancel_update ) rows += [utils.get_dict_properties(data.to_dict(), columns)] else: diff --git a/heatclient/tests/unit/osc/v1/test_stack.py b/heatclient/tests/unit/osc/v1/test_stack.py index f285f56..ecfacf6 100644 --- a/heatclient/tests/unit/osc/v1/test_stack.py +++ b/heatclient/tests/unit/osc/v1/test_stack.py @@ -935,11 +935,12 @@ class _TestStackCheckBase(object): columns = ['ID', 'Stack Name', 'Stack Status', 'Creation Time', 'Updated Time'] - def _setUp(self, cmd, action): + def _setUp(self, cmd, action, action_name=None): self.cmd = cmd self.action = action self.mock_client.stacks.get = mock.Mock( return_value=self.stack) + self.action_name = action_name def _test_stack_action(self, get_call_count=1): arglist = ['my_stack'] @@ -964,10 +965,14 @@ class _TestStackCheckBase(object): self.assertEqual(self.columns, columns) self.assertEqual(2, len(rows)) - @mock.patch('openstackclient.common.utils.wait_for_status', - return_value=True) - def _test_stack_action_wait(self, mock_wait): + @mock.patch('heatclient.common.event_utils.poll_for_events') + @mock.patch('heatclient.common.event_utils.get_events', return_value=[]) + def _test_stack_action_wait(self, ge, mock_poll): arglist = ['my_stack', '--wait'] + mock_poll.return_value = ( + '%s_COMPLETE' % self.action_name, + 'Stack my_stack %s_COMPLETE' % self.action_name + ) parsed_args = self.check_parser(self.cmd, arglist, []) columns, rows = self.cmd.take_action(parsed_args) self.action.assert_called_with('my_stack') @@ -975,10 +980,14 @@ class _TestStackCheckBase(object): self.assertEqual(self.columns, columns) self.assertEqual(1, len(rows)) - @mock.patch('openstackclient.common.utils.wait_for_status', - return_value=False) - def _test_stack_action_wait_error(self, mock_wait): + @mock.patch('heatclient.common.event_utils.poll_for_events') + @mock.patch('heatclient.common.event_utils.get_events', return_value=[]) + def _test_stack_action_wait_error(self, ge, mock_poll): arglist = ['my_stack', '--wait'] + mock_poll.return_value = ( + '%s_FAILED' % self.action_name, + 'Error waiting for status from stack my_stack' + ) parsed_args = self.check_parser(self.cmd, arglist, []) error = self.assertRaises(exc.CommandError, self.cmd.take_action, @@ -1004,7 +1013,8 @@ class TestStackSuspend(_TestStackCheckBase, TestStack): self.mock_client.actions.suspend = mock.Mock() self._setUp( stack.SuspendStack(self.app, None), - self.mock_client.actions.suspend + self.mock_client.actions.suspend, + 'SUSPEND' ) def test_stack_suspend(self): @@ -1030,7 +1040,8 @@ class TestStackResume(_TestStackCheckBase, TestStack): self.mock_client.actions.resume = mock.Mock() self._setUp( stack.ResumeStack(self.app, None), - self.mock_client.actions.resume + self.mock_client.actions.resume, + 'RESUME' ) def test_stack_resume(self): @@ -1064,7 +1075,8 @@ class TestStackCancel(_TestStackCheckBase, TestStack): self.mock_client.actions.cancel_update = mock.Mock() self._setUp( stack.CancelStack(self.app, None), - self.mock_client.actions.cancel_update + self.mock_client.actions.cancel_update, + 'ROLLBACK' ) self.mock_client.stacks.get = mock.Mock( return_value=self.stack_update_in_progress) @@ -1102,7 +1114,8 @@ class TestStackCheck(_TestStackCheckBase, TestStack): self.mock_client.actions.check = mock.Mock() self._setUp( stack.CheckStack(self.app, None), - self.mock_client.actions.check + self.mock_client.actions.check, + 'CHECK' ) def test_stack_check(self): |
