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:
tengqm 2014-11-26 20:01:38 +08:00
parent 5596e63263
commit 11dc22a701
11 changed files with 242 additions and 100 deletions

62
heat/common/grouputils.py Normal file
View File

@ -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)]

View File

@ -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]

View File

@ -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])

View File

@ -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:

View File

@ -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')

View File

@ -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'])

View File

@ -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

View File

@ -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))

View File

@ -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):

View File

@ -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

View File

@ -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])