Extract group functions into a utility module.
This patch extracts group checking functions into a dedicated module so that resource implementations are simplified. The module could later be used by the autoscaling engine as well. Change-Id: I99cdd8c9e8fe377e6923ab047a9c2ef08d1defad partial-blueprint: reorg-asg-code partial-blueprint: as-lib
This commit is contained in:
parent
5596e63263
commit
11dc22a701
|
@ -0,0 +1,62 @@
|
|||
#
|
||||
# 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
|
||||
|
||||
|
||||
def get_size(group):
|
||||
"""Get number of member resources managed by the specified group.
|
||||
|
||||
The list of members are not sorted or returned.
|
||||
"""
|
||||
if group.nested():
|
||||
resources = [r for r in six.itervalues(group.nested())
|
||||
if r.status != r.FAILED]
|
||||
return len(resources)
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def get_members(group):
|
||||
"""Get a list of member resources managed by the specified group.
|
||||
|
||||
Sort the list of instances first by created_time then by name.
|
||||
"""
|
||||
resources = []
|
||||
if group.nested():
|
||||
resources = [r for r in six.itervalues(group.nested())
|
||||
if r.status != r.FAILED]
|
||||
|
||||
return sorted(resources, key=lambda r: (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)]
|
|
@ -16,6 +16,7 @@ from oslo.utils import excutils
|
|||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common.i18n import _
|
||||
from heat.common.i18n import _LI
|
||||
from heat.engine import constraints
|
||||
|
@ -213,7 +214,7 @@ class AutoScalingGroup(instgrp.InstanceGroup, cooldown.CooldownMixin):
|
|||
done = super(AutoScalingGroup, self).check_create_complete(task)
|
||||
if done:
|
||||
self._cooldown_timestamp(
|
||||
"%s : %s" % (EXACT_CAPACITY, len(self.get_instances())))
|
||||
"%s : %s" % (EXACT_CAPACITY, grouputils.get_size(self)))
|
||||
return done
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
|
@ -241,7 +242,7 @@ class AutoScalingGroup(instgrp.InstanceGroup, cooldown.CooldownMixin):
|
|||
self.adjust(self.properties[self.DESIRED_CAPACITY],
|
||||
adjustment_type=EXACT_CAPACITY)
|
||||
else:
|
||||
current_capacity = len(self.get_instances())
|
||||
current_capacity = grouputils.get_size(self)
|
||||
self.adjust(current_capacity, adjustment_type=EXACT_CAPACITY)
|
||||
|
||||
def adjust(self, adjustment, adjustment_type=CHANGE_IN_CAPACITY):
|
||||
|
@ -255,7 +256,7 @@ class AutoScalingGroup(instgrp.InstanceGroup, cooldown.CooldownMixin):
|
|||
'cooldown': self.properties[self.COOLDOWN]})
|
||||
return
|
||||
|
||||
capacity = len(self.get_instances())
|
||||
capacity = grouputils.get_size(self)
|
||||
lower = self.properties[self.MIN_SIZE]
|
||||
upper = self.properties[self.MAX_SIZE]
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import copy
|
|||
|
||||
from heat.common import environment_format
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common.i18n import _
|
||||
from heat.common import timeutils as iso8601utils
|
||||
from heat.engine import attributes
|
||||
|
@ -165,24 +166,6 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
lc=self.LAUNCH_CONFIGURATION_NAME,
|
||||
ref=conf_refid))
|
||||
|
||||
def get_instance_names(self):
|
||||
"""Get a list of resource names of the instances in this InstanceGroup.
|
||||
|
||||
Failed resources will be ignored.
|
||||
"""
|
||||
return [r.name for r in self.get_instances()]
|
||||
|
||||
def get_instances(self):
|
||||
"""Get a list of all the instance resources managed by this group.
|
||||
|
||||
Sort the list of instances first by created_time then by name.
|
||||
"""
|
||||
resources = []
|
||||
if self.nested():
|
||||
resources = [resource for resource in self.nested().itervalues()
|
||||
if resource.status != resource.FAILED]
|
||||
return sorted(resources, key=lambda r: (r.created_time, r.name))
|
||||
|
||||
def _environment(self):
|
||||
"""Return the environment for the nested stack."""
|
||||
return {
|
||||
|
@ -232,8 +215,8 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
# Get the current capacity, we may need to adjust if
|
||||
# Size has changed
|
||||
if self.SIZE in prop_diff:
|
||||
inst_list = self.get_instances()
|
||||
if len(inst_list) != self.properties[self.SIZE]:
|
||||
curr_size = grouputils.get_size(self)
|
||||
if curr_size != self.properties[self.SIZE]:
|
||||
self.resize(self.properties[self.SIZE])
|
||||
|
||||
def _tags(self):
|
||||
|
@ -270,7 +253,7 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
def _get_instance_templates(self):
|
||||
"""Get templates for resource instances."""
|
||||
return [(instance.name, instance.t)
|
||||
for instance in self.get_instances()]
|
||||
for instance in grouputils.get_members(self)]
|
||||
|
||||
def _create_template(self, num_instances, num_replace=0,
|
||||
template_version=('HeatTemplateFormatVersion',
|
||||
|
@ -301,7 +284,7 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
Replace the instances in the group using updated launch configuration
|
||||
"""
|
||||
def changing_instances(tmpl):
|
||||
instances = self.get_instances()
|
||||
instances = grouputils.get_members(self)
|
||||
current = set((i.name, i.t) for i in instances)
|
||||
updated = set(tmpl.resource_definitions(self.nested()).items())
|
||||
# includes instances to be updated and deleted
|
||||
|
@ -374,8 +357,7 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
'''
|
||||
exclude = exclude or []
|
||||
if self.properties[self.LOAD_BALANCER_NAMES]:
|
||||
id_list = [inst.FnGetRefId() for inst in self.get_instances()
|
||||
if inst.FnGetRefId() not in exclude]
|
||||
id_list = grouputils.get_member_refids(self, exclude=exclude)
|
||||
for lb in self.properties[self.LOAD_BALANCER_NAMES]:
|
||||
lb_resource = self.stack[lb]
|
||||
|
||||
|
@ -408,7 +390,7 @@ class InstanceGroup(stack_resource.StackResource):
|
|||
'''
|
||||
if name == self.INSTANCE_LIST:
|
||||
return u','.join(inst.FnGetAtt('PublicIp')
|
||||
for inst in self.get_instances()) or None
|
||||
for inst in grouputils.get_members(self)) or None
|
||||
|
||||
def child_template(self):
|
||||
num_instances = int(self.properties[self.SIZE])
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# under the License.
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import attributes
|
||||
from heat.engine import constraints
|
||||
|
@ -148,10 +149,10 @@ class AutoScalingResourceGroup(aws_asg.AutoScalingGroup):
|
|||
|
||||
def FnGetAtt(self, key, *path):
|
||||
if key == self.CURRENT_SIZE:
|
||||
return len(self.get_instances())
|
||||
return grouputils.get_size(self)
|
||||
if path:
|
||||
attrs = ((rsrc.name,
|
||||
rsrc.FnGetAtt(*path)) for rsrc in self.get_instances())
|
||||
members = grouputils.get_members(self)
|
||||
attrs = ((rsrc.name, rsrc.FnGetAtt(*path)) for rsrc in members)
|
||||
if key == self.OUTPUTS:
|
||||
return dict(attrs)
|
||||
if key == self.OUTPUTS_LIST:
|
||||
|
|
|
@ -16,6 +16,7 @@ from oslo.config import cfg
|
|||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import template_format
|
||||
from heat.engine import scheduler
|
||||
from heat.tests.autoscaling import inline_templates
|
||||
|
@ -178,14 +179,14 @@ class TestGroupAdjust(common.HeatTestCase):
|
|||
def test_scaling_policy_cooldown_toosoon(self):
|
||||
"""If _cooldown_inprogress() returns True don't progress."""
|
||||
|
||||
dont_call = self.patchobject(self.group, 'get_instances')
|
||||
dont_call = self.patchobject(grouputils, 'get_members')
|
||||
with mock.patch.object(self.group, '_cooldown_inprogress',
|
||||
return_value=True):
|
||||
self.group.adjust(1)
|
||||
self.assertEqual([], dont_call.call_args_list)
|
||||
|
||||
def test_scaling_policy_cooldown_ok(self):
|
||||
self.patchobject(self.group, 'get_instances', return_value=[])
|
||||
self.patchobject(grouputils, 'get_members', return_value=[])
|
||||
resize = self.patchobject(self.group, 'resize')
|
||||
cd_stamp = self.patchobject(self.group, '_cooldown_timestamp')
|
||||
notify = self.patch('heat.engine.notification.autoscaling.send')
|
||||
|
@ -213,7 +214,7 @@ class TestGroupAdjust(common.HeatTestCase):
|
|||
cd_stamp.assert_called_once_with('ChangeInCapacity : 1')
|
||||
|
||||
def test_scaling_policy_resize_fail(self):
|
||||
self.patchobject(self.group, 'get_instances', return_value=[])
|
||||
self.patchobject(grouputils, 'get_members', return_value=[])
|
||||
self.patchobject(self.group, 'resize',
|
||||
side_effect=ValueError('test error'))
|
||||
notify = self.patch('heat.engine.notification.autoscaling.send')
|
||||
|
|
|
@ -20,6 +20,7 @@ from oslo.utils import timeutils
|
|||
import six
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import short_id
|
||||
from heat.common import template_format
|
||||
from heat.engine.notification import autoscaling as notification
|
||||
|
@ -260,7 +261,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
props = copy.copy(rsrc.properties.data)
|
||||
props['AvailabilityZones'] = ['foo']
|
||||
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
|
||||
|
@ -284,7 +285,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
@ -311,7 +312,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
@ -344,7 +345,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(2, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(2, len(grouputils.get_member_names(rsrc)))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
@ -374,7 +375,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(2, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(2, len(grouputils.get_member_names(rsrc)))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
@ -406,7 +407,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
@ -436,7 +437,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
@ -480,7 +481,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
scheduler.TaskRunner(rsrc.create))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
|
||||
|
||||
self.assertEqual([], rsrc.get_instance_names())
|
||||
self.assertEqual([], grouputils.get_members(rsrc))
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
|
@ -520,7 +521,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
|
||||
rsrc.FnGetRefId())
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
props = copy.copy(rsrc.properties.data)
|
||||
props['Cooldown'] = '61'
|
||||
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
|
||||
|
@ -627,7 +628,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
self.m.ReplayAll()
|
||||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
stack.resources['WebServerGroup'] = rsrc
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
|
||||
# Scale up one
|
||||
self._stub_lb_reload(2)
|
||||
|
@ -641,7 +642,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
alarm_url = up_policy.FnGetAtt('AlarmUrl')
|
||||
self.assertIsNotNone(alarm_url)
|
||||
up_policy.signal()
|
||||
self.assertEqual(2, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(2, len(grouputils.get_member_names(rsrc)))
|
||||
|
||||
# Check CustomLB metadata was updated
|
||||
self.m.StubOutWithMock(instance.Instance, '_ipaddress')
|
||||
|
@ -668,7 +669,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
self.m.ReplayAll()
|
||||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
stack.resources['WebServerGroup'] = rsrc
|
||||
self.assertEqual(1, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(1, len(grouputils.get_member_names(rsrc)))
|
||||
|
||||
# Create initial scaling policy
|
||||
up_policy = self.create_scaling_policy(t, stack,
|
||||
|
@ -683,7 +684,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
|
||||
# Trigger alarm
|
||||
up_policy.signal()
|
||||
self.assertEqual(2, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(2, len(grouputils.get_member_names(rsrc)))
|
||||
|
||||
# Update scaling policy
|
||||
props = copy.copy(up_policy.properties.data)
|
||||
|
@ -717,7 +718,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
|
||||
# Trigger alarm
|
||||
up_policy.signal()
|
||||
self.assertEqual(4, len(rsrc.get_instance_names()))
|
||||
self.assertEqual(4, len(grouputils.get_member_names(rsrc)))
|
||||
|
||||
rsrc.delete()
|
||||
self.m.VerifyAll()
|
||||
|
@ -736,7 +737,7 @@ class AutoScalingTest(common.HeatTestCase):
|
|||
self.m.ReplayAll()
|
||||
|
||||
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
|
||||
instances = rsrc.get_instances()
|
||||
instances = grouputils.get_members(rsrc)
|
||||
self.assertEqual(1, len(instances))
|
||||
self.assertEqual('xxxx', instances[0].properties['SubnetId'])
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ from oslo.config import cfg
|
|||
from testtools.matchers import MatchesRegex
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import template_format
|
||||
from heat.engine.clients.os import nova
|
||||
from heat.engine import function
|
||||
|
@ -494,8 +495,8 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
self.m.UnsetStubs()
|
||||
|
||||
# saves info from initial list of instances for comparison later
|
||||
init_instances = current_grp.get_instances()
|
||||
init_names = current_grp.get_instance_names()
|
||||
init_instances = grouputils.get_members(current_grp)
|
||||
init_names = grouputils.get_member_names(current_grp)
|
||||
init_images = [(i.name, i.t['Properties']['ImageId'])
|
||||
for i in init_instances]
|
||||
init_flavors = [(i.name, i.t['Properties']['InstanceType'])
|
||||
|
@ -527,7 +528,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
|
||||
# test that the update policy is updated
|
||||
updated_grp = stack['WebServerGroup']
|
||||
updt_instances = updated_grp.get_instances()
|
||||
updt_instances = grouputils.get_members(updated_grp)
|
||||
self.assertTrue('AutoScalingRollingUpdate'
|
||||
in updated_grp.update_policy)
|
||||
updated_policy = updated_grp.update_policy['AutoScalingRollingUpdate']
|
||||
|
@ -540,8 +541,8 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
self.assertNotEqual(conf_name, updated_conf_name)
|
||||
|
||||
# test that the group size are the same
|
||||
updt_instances = updated_grp.get_instances()
|
||||
updt_names = updated_grp.get_instance_names()
|
||||
updt_instances = grouputils.get_members(updated_grp)
|
||||
updt_names = grouputils.get_member_names(updated_grp)
|
||||
self.assertEqual(len(init_names), len(updt_names))
|
||||
|
||||
# test that appropriate number of instance names are the same
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
#
|
||||
# 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 mock
|
||||
|
||||
from heat.common import grouputils
|
||||
from heat.common import template_format
|
||||
from heat.engine import resource
|
||||
from heat.tests import common
|
||||
from heat.tests import generic_resource
|
||||
from heat.tests import utils
|
||||
|
||||
nested_stack = '''
|
||||
heat_template_version: 2013-05-23
|
||||
resources:
|
||||
r0:
|
||||
type: dummy.resource
|
||||
r1:
|
||||
type: dummy.resource
|
||||
'''
|
||||
|
||||
|
||||
class SimpleResource(generic_resource.ResourceWithProps):
|
||||
|
||||
def FnGetRefId(self):
|
||||
return 'ID-%s' % self.name
|
||||
|
||||
|
||||
class GroupUtilsTest(common.HeatTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(GroupUtilsTest, self).setUp()
|
||||
resource._register_class('dummy.resource', SimpleResource)
|
||||
|
||||
def test_non_nested_resource(self):
|
||||
group = mock.Mock()
|
||||
self.patchobject(group, 'nested', return_value=None)
|
||||
|
||||
self.assertEqual(0, grouputils.get_size(group))
|
||||
self.assertEqual([], grouputils.get_members(group))
|
||||
self.assertEqual([], grouputils.get_member_refids(group))
|
||||
self.assertEqual([], grouputils.get_member_names(group))
|
||||
|
||||
def test_normal_group(self):
|
||||
group = mock.Mock()
|
||||
t = template_format.parse(nested_stack)
|
||||
stack = utils.parse_stack(t)
|
||||
|
||||
# group size
|
||||
self.patchobject(group, 'nested', return_value=stack)
|
||||
self.assertEqual(2, grouputils.get_size(group))
|
||||
|
||||
# member list (sorted)
|
||||
members = [r for r in stack.itervalues()]
|
||||
expected = sorted(members, key=lambda r: (r.created_time, r.name))
|
||||
actual = grouputils.get_members(group)
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
# refids
|
||||
actual_ids = grouputils.get_member_refids(group)
|
||||
self.assertEqual(['ID-r0', 'ID-r1'], actual_ids)
|
||||
partial_ids = grouputils.get_member_refids(group, exclude=['ID-r1'])
|
||||
self.assertEqual(['ID-r0'], partial_ids)
|
||||
|
||||
# names
|
||||
self.assertEqual(['r0', 'r1'], grouputils.get_member_names(group))
|
||||
|
||||
def test_group_with_failed_members(self):
|
||||
group = mock.Mock()
|
||||
t = template_format.parse(nested_stack)
|
||||
stack = utils.parse_stack(t)
|
||||
self.patchobject(group, 'nested', return_value=stack)
|
||||
|
||||
# Just failed for whatever reason
|
||||
rsrc_err = stack.resources['r0']
|
||||
rsrc_err.status = rsrc_err.FAILED
|
||||
rsrc_ok = stack.resources['r1']
|
||||
|
||||
self.assertEqual(1, grouputils.get_size(group))
|
||||
self.assertEqual([rsrc_ok], grouputils.get_members(group))
|
||||
self.assertEqual(['ID-r1'], grouputils.get_member_refids(group))
|
||||
self.assertEqual(['r1'], grouputils.get_member_names(group))
|
|
@ -18,10 +18,10 @@ from oslo.config import cfg
|
|||
from oslo.utils import timeutils
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import short_id
|
||||
from heat.common import template_format
|
||||
from heat.engine import resource
|
||||
from heat.engine.resources.openstack import autoscaling_group as asg
|
||||
from heat.engine import rsrc_defn
|
||||
from heat.engine import scheduler
|
||||
from heat.engine import stack_resource
|
||||
|
@ -67,7 +67,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
properties['min_size'] = 0
|
||||
properties['max_size'] = 0
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(0, len(rsrc.get_instances()))
|
||||
self.assertEqual(0, grouputils.get_size(rsrc))
|
||||
rsrc.delete()
|
||||
|
||||
def test_scaling_adjust_down_empty(self):
|
||||
|
@ -75,7 +75,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
properties['min_size'] = 1
|
||||
properties['max_size'] = 1
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
resources = rsrc.get_instances()
|
||||
resources = grouputils.get_members(rsrc)
|
||||
self.assertEqual(1, len(resources))
|
||||
|
||||
# Reduce the min size to 0, should complete without adjusting
|
||||
|
@ -85,22 +85,22 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
rsrc.type(),
|
||||
props)
|
||||
scheduler.TaskRunner(rsrc.update, update_snippet)()
|
||||
self.assertEqual(resources, rsrc.get_instances())
|
||||
self.assertEqual(resources, grouputils.get_members(rsrc))
|
||||
|
||||
# trigger adjustment to reduce to 0, there should be no more instances
|
||||
rsrc.adjust(-1)
|
||||
self.assertEqual(0, len(rsrc.get_instances()))
|
||||
self.assertEqual(0, grouputils.get_size(rsrc))
|
||||
|
||||
def test_scaling_group_suspend(self):
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
scheduler.TaskRunner(rsrc.suspend)()
|
||||
self.assertEqual((rsrc.SUSPEND, rsrc.COMPLETE), rsrc.state)
|
||||
|
||||
def test_scaling_group_resume(self):
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
|
||||
rsrc.state_set(rsrc.SUSPEND, rsrc.COMPLETE)
|
||||
for i in rsrc.nested().values():
|
||||
|
@ -120,7 +120,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
scheduler.TaskRunner(rsrc.create))
|
||||
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
|
||||
|
||||
self.assertEqual(0, len(rsrc.get_instances()))
|
||||
self.assertEqual(0, grouputils.get_size(rsrc))
|
||||
|
||||
def test_scaling_group_update_ok_maxsize(self):
|
||||
properties = self.parsed['resources']['my-group']['properties']
|
||||
|
@ -128,7 +128,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
properties['max_size'] = 3
|
||||
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
resources = rsrc.get_instances()
|
||||
resources = grouputils.get_members(rsrc)
|
||||
self.assertEqual(1, len(resources))
|
||||
|
||||
# Reduce the max size to 2, should complete without adjusting
|
||||
|
@ -138,7 +138,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
rsrc.type(),
|
||||
props)
|
||||
scheduler.TaskRunner(rsrc.update, update_snippet)()
|
||||
self.assertEqual(resources, rsrc.get_instances())
|
||||
self.assertEqual(resources, grouputils.get_members(rsrc))
|
||||
self.assertEqual(2, rsrc.properties['max_size'])
|
||||
|
||||
def test_scaling_group_update_ok_minsize(self):
|
||||
|
@ -147,7 +147,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
properties['max_size'] = 3
|
||||
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
|
||||
props = copy.copy(rsrc.properties.data)
|
||||
props['min_size'] = 2
|
||||
|
@ -155,7 +155,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
rsrc.type(),
|
||||
props)
|
||||
scheduler.TaskRunner(rsrc.update, update_snippet)()
|
||||
self.assertEqual(2, len(rsrc.get_instances()))
|
||||
self.assertEqual(2, grouputils.get_size(rsrc))
|
||||
self.assertEqual(2, rsrc.properties['min_size'])
|
||||
|
||||
def test_scaling_group_update_ok_desired(self):
|
||||
|
@ -163,7 +163,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
properties['min_size'] = 1
|
||||
properties['max_size'] = 3
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
|
||||
props = copy.copy(rsrc.properties.data)
|
||||
props['desired_capacity'] = 2
|
||||
|
@ -171,14 +171,14 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
rsrc.type(),
|
||||
props)
|
||||
scheduler.TaskRunner(rsrc.update, update_snippet)()
|
||||
self.assertEqual(2, len(rsrc.get_instances()))
|
||||
self.assertEqual(2, grouputils.get_size(rsrc))
|
||||
self.assertEqual(2, rsrc.properties['desired_capacity'])
|
||||
|
||||
def test_scaling_group_update_ok_desired_remove(self):
|
||||
properties = self.parsed['resources']['my-group']['properties']
|
||||
properties['desired_capacity'] = 2
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
resources = rsrc.get_instances()
|
||||
resources = grouputils.get_members(rsrc)
|
||||
self.assertEqual(2, len(resources))
|
||||
|
||||
props = copy.copy(rsrc.properties.data)
|
||||
|
@ -187,7 +187,7 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
rsrc.type(),
|
||||
props)
|
||||
scheduler.TaskRunner(rsrc.update, update_snippet)()
|
||||
self.assertEqual(resources, rsrc.get_instances())
|
||||
self.assertEqual(resources, grouputils.get_members(rsrc))
|
||||
self.assertIsNone(rsrc.properties['desired_capacity'])
|
||||
|
||||
def test_scaling_group_scale_up_failure(self):
|
||||
|
@ -195,27 +195,27 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
mock_create = self.patchobject(generic_resource.ResourceWithProps,
|
||||
'handle_create')
|
||||
rsrc = stack['my-group']
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
|
||||
mock_create.side_effect = exception.Error('Bang')
|
||||
self.assertRaises(exception.Error, rsrc.adjust, 1)
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
|
||||
def test_scaling_group_truncate_adjustment(self):
|
||||
# Create initial group, 2 instances
|
||||
properties = self.parsed['resources']['my-group']['properties']
|
||||
properties['desired_capacity'] = 2
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(2, len(rsrc.get_instances()))
|
||||
self.assertEqual(2, grouputils.get_size(rsrc))
|
||||
|
||||
rsrc.adjust(4)
|
||||
self.assertEqual(5, len(rsrc.get_instances()))
|
||||
self.assertEqual(5, grouputils.get_size(rsrc))
|
||||
|
||||
rsrc.adjust(-5)
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
|
||||
rsrc.adjust(0)
|
||||
self.assertEqual(1, len(rsrc.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(rsrc))
|
||||
|
||||
def _do_test_scaling_group_percent(self, decrease, lowest,
|
||||
increase, create, highest):
|
||||
|
@ -223,15 +223,15 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
properties = self.parsed['resources']['my-group']['properties']
|
||||
properties['desired_capacity'] = 2
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
self.assertEqual(2, len(rsrc.get_instances()))
|
||||
self.assertEqual(2, grouputils.get_size(rsrc))
|
||||
|
||||
# reduce by decrease %
|
||||
rsrc.adjust(decrease, 'percentage_change_in_capacity')
|
||||
self.assertEqual(lowest, len(rsrc.get_instances()))
|
||||
self.assertEqual(lowest, grouputils.get_size(rsrc))
|
||||
|
||||
# raise by increase %
|
||||
rsrc.adjust(increase, 'percentage_change_in_capacity')
|
||||
self.assertEqual(highest, len(rsrc.get_instances()))
|
||||
self.assertEqual(highest, grouputils.get_size(rsrc))
|
||||
|
||||
def test_scaling_group_percent(self):
|
||||
self._do_test_scaling_group_percent(-50, 1, 200, 2, 3)
|
||||
|
@ -267,17 +267,15 @@ class AutoScalingGroupTest(common.HeatTestCase):
|
|||
|
||||
def test_attribute_current_size(self):
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
mock_instances = self.patchobject(asg.AutoScalingResourceGroup,
|
||||
'get_instances')
|
||||
mock_instances.return_value = ['one', 'two', 'three']
|
||||
mock_instances = self.patchobject(grouputils, 'get_size')
|
||||
mock_instances.return_value = 3
|
||||
|
||||
self.assertEqual(3, rsrc.FnGetAtt('current_size'))
|
||||
|
||||
def test_attribute_current_size_with_path(self):
|
||||
rsrc = self.create_stack(self.parsed)['my-group']
|
||||
mock_instances = self.patchobject(asg.AutoScalingResourceGroup,
|
||||
'get_instances')
|
||||
mock_instances.return_value = ['one', 'two', 'three', 'four']
|
||||
mock_instances = self.patchobject(grouputils, 'get_size')
|
||||
mock_instances.return_value = 4
|
||||
self.assertEqual(4, rsrc.FnGetAtt('current_size', 'name'))
|
||||
|
||||
|
||||
|
@ -323,9 +321,9 @@ class HeatScalingGroupWithCFNScalingPolicyTest(common.HeatTestCase):
|
|||
stack = self.create_stack(self.parsed)
|
||||
scale_up = stack['scale-up']
|
||||
group = stack['my-group']
|
||||
self.assertEqual(1, len(group.get_instances()))
|
||||
self.assertEqual(1, grouputils.get_size(group))
|
||||
scale_up.signal()
|
||||
self.assertEqual(2, len(group.get_instances()))
|
||||
self.assertEqual(2, grouputils.get_size(group))
|
||||
|
||||
def test_no_instance_list(self):
|
||||
"""
|
||||
|
@ -382,9 +380,9 @@ class ScalingPolicyTest(common.HeatTestCase):
|
|||
|
||||
self.assertEqual("1234", policy.FnGetRefId())
|
||||
|
||||
self.assertEqual(1, len(group.get_instance_names()))
|
||||
self.assertEqual(1, grouputils.get_size(group))
|
||||
policy.signal()
|
||||
self.assertEqual(2, len(group.get_instance_names()))
|
||||
self.assertEqual(2, grouputils.get_size(group))
|
||||
|
||||
def test_signal_with_cooldown(self):
|
||||
self.parsed['resources']['my-policy']['properties']['cooldown'] = 60
|
||||
|
@ -393,19 +391,20 @@ class ScalingPolicyTest(common.HeatTestCase):
|
|||
policy = stack['my-policy']
|
||||
group = stack['my-group']
|
||||
|
||||
self.assertEqual(1, len(group.get_instance_names()))
|
||||
self.assertEqual(1, grouputils.get_size(group))
|
||||
policy.signal()
|
||||
self.assertEqual(2, len(group.get_instance_names()))
|
||||
self.assertEqual(2, grouputils.get_size(group))
|
||||
policy.signal()
|
||||
# The second signal shouldn't have changed it because of cooldown
|
||||
self.assertEqual(2, len(group.get_instance_names()))
|
||||
self.assertEqual(2, grouputils.get_size(group))
|
||||
|
||||
past = timeutils.strtime(timeutils.utcnow() -
|
||||
datetime.timedelta(seconds=65))
|
||||
policy.metadata_set({past: 'ChangeInCapacity : 1'})
|
||||
|
||||
policy.signal()
|
||||
self.assertEqual(3, len(group.get_instance_names()))
|
||||
|
||||
self.assertEqual(3, grouputils.get_size(group))
|
||||
|
||||
|
||||
class RollingUpdatesTest(common.HeatTestCase):
|
||||
|
|
|
@ -18,6 +18,7 @@ import mox
|
|||
from testtools.matchers import MatchesRegex
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import template_format
|
||||
from heat.engine.clients.os import nova
|
||||
from heat.engine import function
|
||||
|
@ -406,8 +407,8 @@ class InstanceGroupTest(common.HeatTestCase):
|
|||
self.m.UnsetStubs()
|
||||
|
||||
# saves info from initial list of instances for comparison later
|
||||
init_instances = current_grp.get_instances()
|
||||
init_names = current_grp.get_instance_names()
|
||||
init_instances = grouputils.get_members(current_grp)
|
||||
init_names = grouputils.get_member_names(current_grp)
|
||||
init_images = [(i.name, i.t['Properties']['ImageId'])
|
||||
for i in init_instances]
|
||||
init_flavors = [(i.name, i.t['Properties']['InstanceType'])
|
||||
|
@ -444,8 +445,8 @@ class InstanceGroupTest(common.HeatTestCase):
|
|||
self.assertNotEqual(conf_name, updated_conf_name)
|
||||
|
||||
# test that the group size are the same
|
||||
updt_instances = updated_grp.get_instances()
|
||||
updt_names = updated_grp.get_instance_names()
|
||||
updt_instances = grouputils.get_members(updated_grp)
|
||||
updt_names = grouputils.get_member_names(updated_grp)
|
||||
self.assertEqual(len(init_names), len(updt_names))
|
||||
|
||||
# test that the appropriate number of instance names are the same
|
||||
|
|
|
@ -15,6 +15,7 @@ import mock
|
|||
from oslo.utils import timeutils
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import grouputils
|
||||
from heat.common import template_format
|
||||
from heat.engine.clients.os import glance
|
||||
from heat.engine.clients.os import nova
|
||||
|
@ -252,7 +253,7 @@ class ScaleNotificationTest(common.HeatTestCase):
|
|||
end_capacity=2,
|
||||
)
|
||||
group.adjust(1)
|
||||
self.assertEqual(2, len(group.get_instance_names()))
|
||||
self.assertEqual(2, grouputils.get_size(group))
|
||||
mock_notify.assert_has_calls(expected)
|
||||
|
||||
expected = self.expected_notifs_calls(group,
|
||||
|
@ -261,7 +262,7 @@ class ScaleNotificationTest(common.HeatTestCase):
|
|||
end_capacity=1,
|
||||
)
|
||||
group.adjust(-1)
|
||||
self.assertEqual(1, len(group.get_instance_names()))
|
||||
self.assertEqual(1, grouputils.get_size(group))
|
||||
mock_notify.assert_has_calls(expected)
|
||||
|
||||
@mock.patch('heat.engine.notification.stack.send')
|
||||
|
@ -280,6 +281,6 @@ class ScaleNotificationTest(common.HeatTestCase):
|
|||
start_capacity=1,
|
||||
with_error=err_message)
|
||||
self.assertRaises(exception.Error, group.adjust, 2)
|
||||
self.assertEqual(1, len(group.get_instance_names()))
|
||||
self.assertEqual(1, grouputils.get_size(group))
|
||||
mock_error.assert_has_calls([error])
|
||||
mock_info.assert_has_calls([info])
|
||||
|
|
Loading…
Reference in New Issue