shade/shade/_heat/event_utils.py

105 lines
3.5 KiB
Python

# Copyright 2015 Red Hat Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import collections
import time
from shade import meta
def get_events(cloud, stack_id, event_args, marker=None, limit=None):
# TODO(mordred) FIX THIS ONCE assert_calls CAN HANDLE QUERY STRINGS
params = collections.OrderedDict()
for k in sorted(event_args.keys()):
params[k] = event_args[k]
if marker:
event_args['marker'] = marker
if limit:
event_args['limit'] = limit
data = cloud._orchestration_client.get(
'/stacks/{id}/events'.format(id=stack_id),
params=params)
events = meta.get_and_munchify('events', data)
# Show which stack the event comes from (for nested events)
for e in events:
e['stack_name'] = stack_id.split("/")[0]
return events
def poll_for_events(
cloud, stack_name, action=None, poll_period=5, marker=None):
"""Continuously poll events and logs for performed action on stack."""
def stop_check_action(a):
stop_status = ('%s_FAILED' % action, '%s_COMPLETE' % action)
return a in stop_status
def stop_check_no_action(a):
return a.endswith('_COMPLETE') or a.endswith('_FAILED')
if action:
stop_check = stop_check_action
else:
stop_check = stop_check_no_action
no_event_polls = 0
msg_template = "\n Stack %(name)s %(status)s \n"
def is_stack_event(event):
if event.get('resource_name', '') != stack_name:
return False
phys_id = event.get('physical_resource_id', '')
links = dict((l.get('rel'),
l.get('href')) for l in event.get('links', []))
stack_id = links.get('stack', phys_id).rsplit('/', 1)[-1]
return stack_id == phys_id
while True:
events = get_events(
cloud, stack_id=stack_name,
event_args={'sort_dir': 'asc', 'marker': marker})
if len(events) == 0:
no_event_polls += 1
else:
no_event_polls = 0
# set marker to last event that was received.
marker = getattr(events[-1], 'id', None)
for event in events:
# check if stack event was also received
if is_stack_event(event):
stack_status = getattr(event, 'resource_status', '')
msg = msg_template % dict(
name=stack_name, status=stack_status)
if stop_check(stack_status):
return stack_status, msg
if no_event_polls >= 2:
# after 2 polls with no events, fall back to a stack get
stack = cloud.get_stack(stack_name, resolve_outputs=False)
stack_status = stack['stack_status']
msg = msg_template % dict(
name=stack_name, status=stack_status)
if stop_check(stack_status):
return stack_status, msg
# go back to event polling again
no_event_polls = 0
time.sleep(poll_period)