
Based on python-heatclient 04b3880 (2015-06-04) Change-Id: Ie54c889a4b89ec32f9a00b954560929f35712021
129 lines
5.2 KiB
Python
129 lines
5.2 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.
|
|
|
|
from stacktaskclient.common import utils
|
|
import stacktaskclient.exc as exc
|
|
|
|
from stacktaskclient.openstack.common._i18n import _
|
|
|
|
|
|
def get_hook_events(hc, stack_id, event_args, nested_depth=0,
|
|
hook_type='pre-create'):
|
|
if hook_type == 'pre-create':
|
|
stack_action_reason = 'Stack CREATE started'
|
|
hook_event_reason = 'CREATE paused until Hook pre-create is cleared'
|
|
hook_clear_event_reason = 'Hook pre-create is cleared'
|
|
elif hook_type == 'pre-update':
|
|
stack_action_reason = 'Stack UPDATE started'
|
|
hook_event_reason = 'UPDATE paused until Hook pre-update is cleared'
|
|
hook_clear_event_reason = 'Hook pre-update is cleared'
|
|
else:
|
|
raise exc.CommandError(_('Unexpected hook type %s') % hook_type)
|
|
|
|
events = get_events(hc, stack_id=stack_id, event_args=event_args,
|
|
nested_depth=nested_depth)
|
|
|
|
# Get the most recent event associated with this action, which gives us the
|
|
# event when we moved into IN_PROGRESS for the hooks we're interested in.
|
|
stack_name = stack_id.split("/")[0]
|
|
action_start_event = [e for e in enumerate(events)
|
|
if e[1].resource_status_reason == stack_action_reason
|
|
and e[1].stack_name == stack_name][-1]
|
|
# Slice the events with the index from the enumerate
|
|
action_start_index = action_start_event[0]
|
|
events = events[action_start_index:]
|
|
|
|
# Get hook events still pending by some list filtering/comparison
|
|
# We build a map hook events per-resource, and remove any event
|
|
# for which there is a corresponding hook-clear event.
|
|
resource_event_map = {}
|
|
for e in events:
|
|
stack_resource = (e.stack_name, e.resource_name)
|
|
if e.resource_status_reason == hook_event_reason:
|
|
resource_event_map[(e.stack_name, e.resource_name)] = e
|
|
elif e.resource_status_reason == hook_clear_event_reason:
|
|
if resource_event_map.get(stack_resource):
|
|
del(resource_event_map[(e.stack_name, e.resource_name)])
|
|
return list(resource_event_map.values())
|
|
|
|
|
|
def get_events(hc, stack_id, event_args, nested_depth=0,
|
|
marker=None, limit=None):
|
|
events = _get_stack_events(hc, stack_id, event_args)
|
|
if nested_depth > 0:
|
|
events.extend(_get_nested_events(hc, nested_depth,
|
|
stack_id, event_args))
|
|
# Because there have been multiple stacks events mangled into
|
|
# one list, we need to sort before passing to print_list
|
|
# Note we can't use the prettytable sortby_index here, because
|
|
# the "start" option doesn't allow post-sort slicing, which
|
|
# will be needed to make "--marker" work for nested_depth lists
|
|
events.sort(key=lambda x: x.event_time)
|
|
|
|
# Slice the list if marker is specified
|
|
if marker:
|
|
marker_index = [e.id for e in events].index(marker)
|
|
events = events[marker_index:]
|
|
|
|
# Slice the list if limit is specified
|
|
if limit:
|
|
limit_index = min(int(limit), len(events))
|
|
events = events[:limit_index]
|
|
return events
|
|
|
|
|
|
def _get_nested_ids(hc, stack_id):
|
|
nested_ids = []
|
|
try:
|
|
resources = hc.resources.list(stack_id=stack_id)
|
|
except exc.HTTPNotFound:
|
|
raise exc.CommandError(_('Stack not found: %s') % stack_id)
|
|
for r in resources:
|
|
nested_id = utils.resource_nested_identifier(r)
|
|
if nested_id:
|
|
nested_ids.append(nested_id)
|
|
return nested_ids
|
|
|
|
|
|
def _get_nested_events(hc, nested_depth, stack_id, event_args):
|
|
# FIXME(shardy): this is very inefficient, we should add nested_depth to
|
|
# the event_list API in a future stacktask version, but this will be required
|
|
# until kilo stacktask is EOL.
|
|
nested_ids = _get_nested_ids(hc, stack_id)
|
|
nested_events = []
|
|
for n_id in nested_ids:
|
|
stack_events = _get_stack_events(hc, n_id, event_args)
|
|
if stack_events:
|
|
nested_events.extend(stack_events)
|
|
if nested_depth > 1:
|
|
next_depth = nested_depth - 1
|
|
nested_events.extend(_get_nested_events(
|
|
hc, next_depth, n_id, event_args))
|
|
return nested_events
|
|
|
|
|
|
def _get_stack_events(hc, stack_id, event_args):
|
|
event_args['stack_id'] = stack_id
|
|
try:
|
|
events = hc.events.list(**event_args)
|
|
except exc.HTTPNotFound as ex:
|
|
# it could be the stack or resource that is not found
|
|
# just use the message that the server sent us.
|
|
raise exc.CommandError(str(ex))
|
|
else:
|
|
# Show which stack the event comes from (for nested events)
|
|
for e in events:
|
|
e.stack_name = stack_id.split("/")[0]
|
|
return events
|