heat/heat/common/grouputils.py
Ahmed Elkhouly 51124ed8c5 InstanceGroup to keep FAILED resources in template
Modify the InstanceGroup (and, by extension, Heat and AWS
AutoscalingGroup) types to give members in a FAILED state the highest
priority for being removed when scaling down or being updated in
a rolling update. Currently, FAILED resources are omitted when building
a new template for the scaling group, so any such resources would never
be replaced by one of the same name. This change will allow for
continuity of naming in the case of a change that doesn't permanently
remove the resource due to scaling down.

Change-Id: I8fe93869dfbe4c4de6c48a65aeef0f71355eaf46
Partially-implements: blueprint mark-unhealthy
2016-01-21 22:22:31 -05:00

115 lines
3.7 KiB
Python

#
# 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 six
from heat.common import exception
def get_size(group, include_failed=False):
"""Get number of member resources managed by the specified group.
The size exclude failed members default, set include_failed=True
to get total size.
"""
if group.nested():
resources = [r for r in six.itervalues(group.nested())
if include_failed or r.status != r.FAILED]
return len(resources)
else:
return 0
def get_members(group, include_failed=False):
"""Get a list of member resources managed by the specified group.
Sort the list of instances first by created_time then by name.
If include_failed is set, failed members will be put first in the
list sorted by created_time then by name.
"""
resources = []
if group.nested():
resources = [r for r in six.itervalues(group.nested())
if include_failed or r.status != r.FAILED]
return sorted(resources,
key=lambda r: (r.status != r.FAILED, r.created_time, r.name))
def get_member_refids(group, exclude=None):
"""Get a list of member resources managed by the specified group.
The list of resources is sorted first by created_time then by name.
"""
members = get_members(group)
if len(members) == 0:
return []
if exclude is None:
exclude = []
return [r.FnGetRefId() for r in members
if r.FnGetRefId() not in exclude]
def get_member_names(group):
"""Get a list of resource names of the resources in the specified group.
Failed resources will be ignored.
"""
return [r.name for r in get_members(group)]
def get_resource(stack, resource_name, use_indices, key):
nested_stack = stack.nested()
if not nested_stack:
return None
try:
if use_indices:
return get_members(stack)[int(resource_name)]
else:
return nested_stack[resource_name]
except (IndexError, KeyError):
raise exception.InvalidTemplateAttribute(resource=stack.name,
key=key)
def get_rsrc_attr(stack, key, use_indices, resource_name, *attr_path):
resource = get_resource(stack, resource_name, use_indices, key)
if resource:
return resource.FnGetAtt(*attr_path)
def get_rsrc_id(stack, key, use_indices, resource_name):
resource = get_resource(stack, resource_name, use_indices, key)
if resource:
return resource.FnGetRefId()
def get_nested_attrs(stack, key, use_indices, *path):
path = key.split(".", 2)[1:] + list(path)
if len(path) > 1:
return get_rsrc_attr(stack, key, use_indices, *path)
else:
return get_rsrc_id(stack, key, use_indices, *path)
def get_member_definitions(group, include_failed=False):
"""Get member definitions in (name, ResourceDefinition) pair for group.
The List is sorted first by created_time then by name.
If include_failed is set, failed members will be put first in the
List sorted by created_time then by name.
"""
return [(resource.name, resource.t)
for resource in get_members(group, include_failed)]