From: Zane Bitter Date: Mon, 4 Mar 2013 10:31:27 +0000 (+0100) Subject: Create autoscaling instances in parallel X-Git-Tag: 2014.1~818^2 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=8dfd53db24610b5c534ab165328ddfb6927deff9;p=openstack-build%2Fheat-build.git Create autoscaling instances in parallel Fixes bug #1136148 Change-Id: I02ea52df85c4ed7f0f16abcfd1ab24b35168a787 Signed-off-by: Zane Bitter --- diff --git a/heat/engine/resources/autoscaling.py b/heat/engine/resources/autoscaling.py index ed1db336..dc0b1023 100644 --- a/heat/engine/resources/autoscaling.py +++ b/heat/engine/resources/autoscaling.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import eventlet + from heat.common import exception from heat.engine import resource @@ -75,11 +77,21 @@ class InstanceGroup(resource.Resource): def __init__(self, name, json_snippet, stack): super(InstanceGroup, self).__init__(name, json_snippet, stack) - # resource_id is a list of resources + self._activating = [] def handle_create(self): self.resize(int(self.properties['Size']), raise_on_error=True) + def check_active(self): + active = all(i.check_active(override=False) for i in self._activating) + if active: + self._activating = [] + return active + + def _wait_for_activation(self): + while not self.check_active(): + eventlet.sleep(1) + def handle_update(self, json_snippet): try: tmpl_diff = self.update_template_diff(json_snippet) @@ -111,6 +123,7 @@ class InstanceGroup(resource.Resource): if len(inst_list) != int(self.properties['Size']): self.resize(int(self.properties['Size']), raise_on_error=True) + self._wait_for_activation() return self.UPDATE_COMPLETE @@ -128,6 +141,15 @@ class InstanceGroup(resource.Resource): def state_set(self, new_state, reason="state changed"): self._store_or_update(new_state, reason) + def check_active(self, override=True): + ''' + By default, report that the instance is active so that we + won't wait for it in create(). + ''' + if override: + return True + return super(GroupedInstance, self).check_active() + conf = self.properties['LaunchConfigurationName'] instance_definition = self.stack.t['Resources'][conf] return GroupedInstance(name, instance_definition, self.stack) @@ -163,6 +185,7 @@ class InstanceGroup(resource.Resource): name = '%s-%d' % (self.name, x) inst = self._make_instance(name) inst_list.append(name) + self._activating.append(inst) self.resource_id_set(','.join(inst_list)) logger.info('creating inst') error_str = inst.create() @@ -298,11 +321,13 @@ class AutoScalingGroup(InstanceGroup, CooldownMixin): if new_capacity is not None: self._adjust(new_capacity) + self._wait_for_activation() return self.UPDATE_COMPLETE def adjust(self, adjustment, adjustment_type='ChangeInCapacity'): self._adjust(adjustment, adjustment_type, False) + self._wait_for_activation() def _adjust(self, adjustment, adjustment_type='ExactCapacity', raise_on_error=True): diff --git a/heat/tests/test_autoscaling.py b/heat/tests/test_autoscaling.py index 026c82c6..57e7e1a1 100644 --- a/heat/tests/test_autoscaling.py +++ b/heat/tests/test_autoscaling.py @@ -17,6 +17,7 @@ import os import datetime import copy +import eventlet import unittest import mox @@ -83,9 +84,15 @@ class AutoScalingTest(unittest.TestCase): return resource def _stub_create(self, num): + self.m.StubOutWithMock(eventlet, 'sleep') + self.m.StubOutWithMock(instance.Instance, 'create') + self.m.StubOutWithMock(instance.Instance, 'check_active') for x in range(num): instance.Instance.create().AndReturn(None) + instance.Instance.check_active().AndReturn(False) + eventlet.sleep(mox.IsA(int)).AndReturn(None) + instance.Instance.check_active().MultipleTimes().AndReturn(True) def _stub_lb_reload(self, expected_list, unset=True): if unset: diff --git a/heat/tests/test_instance_group.py b/heat/tests/test_instance_group.py index fdc255ee..be9d3d38 100644 --- a/heat/tests/test_instance_group.py +++ b/heat/tests/test_instance_group.py @@ -15,6 +15,7 @@ import copy import os +import eventlet import unittest import mox @@ -62,9 +63,15 @@ class InstanceGroupTest(unittest.TestCase): return stack def _stub_create(self, num): + self.m.StubOutWithMock(eventlet, 'sleep') + self.m.StubOutWithMock(instance.Instance, 'create') + self.m.StubOutWithMock(instance.Instance, 'check_active') for x in range(num): instance.Instance.create().AndReturn(None) + instance.Instance.check_active().AndReturn(False) + eventlet.sleep(mox.IsA(int)).AndReturn(None) + instance.Instance.check_active().MultipleTimes().AndReturn(True) def create_instance_group(self, t, stack, resource_name): resource = asc.InstanceGroup(resource_name,