summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-02-25 13:47:52 +0000
committerGerrit Code Review <review@openstack.org>2016-02-25 13:47:52 +0000
commit7887beafe6cf3edd016f6753ff23181ac9c6cf0e (patch)
tree8be8b2734a3c9367716d989aaff5e11ecc54f71c
parent06b2ef0e3ccd0e224c85b6d49a1ff7aa475c581d (diff)
parent302040c759e13ac93c9bf8a6b1acd14c73faaad7 (diff)
downloadpython-heatclient-7887beafe6cf3edd016f6753ff23181ac9c6cf0e.tar.gz
Merge "Move poll_for_events to event_utils"
-rw-r--r--heatclient/common/event_utils.py30
-rw-r--r--heatclient/tests/unit/test_event_utils.py65
-rw-r--r--heatclient/v1/shell.py47
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)