From d6f8dfed1674b3eb186edd57c9b41bba594e24bf Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Mon, 25 Feb 2013 11:19:19 +0000 Subject: [PATCH] Add waitcondition to loadbalancer nested template We want to ensure the LB instance has fully launched before declaring this resource created, otherwise the resource will not be functional and attempts to modify config via metadata updates will fail Change-Id: I879c21302f1c3a75a567d959fc2e398c7bfc3f65 --- heat/engine/resources/loadbalancer.py | 27 ++++++++++++++++++++++++++- heat/tests/test_loadbalancer.py | 16 ++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/heat/engine/resources/loadbalancer.py b/heat/engine/resources/loadbalancer.py index 1b6b38aaa6..5be550fa68 100644 --- a/heat/engine/resources/loadbalancer.py +++ b/heat/engine/resources/loadbalancer.py @@ -145,14 +145,39 @@ lb_template = r''' "KeyName": { "Ref": "KeyName" }, "UserData": { "Fn::Base64": { "Fn::Join": ["", [ "#!/bin/bash -v\n", + "# Helper function\n", + "function error_exit\n", + "{\n", + " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", + { "Ref" : "WaitHandle" }, "'\n", + " exit 1\n", + "}\n", + "/opt/aws/bin/cfn-init -s ", { "Ref": "AWS::StackName" }, " -r LB_instance ", " --region ", { "Ref": "AWS::Region" }, "\n", "# install cfn-hup crontab\n", - "crontab /tmp/cfn-hup-crontab.txt\n" + "crontab /tmp/cfn-hup-crontab.txt\n", + + "# LB setup completed, signal success\n", + "/opt/aws/bin/cfn-signal -e 0 -r \"LB server setup complete\" '", + { "Ref" : "WaitHandle" }, "'\n" + ]]}} } + }, + "WaitHandle" : { + "Type" : "AWS::CloudFormation::WaitConditionHandle" + }, + + "WaitCondition" : { + "Type" : "AWS::CloudFormation::WaitCondition", + "DependsOn" : "LB_instance", + "Properties" : { + "Handle" : {"Ref" : "WaitHandle"}, + "Timeout" : "600" + } } }, diff --git a/heat/tests/test_loadbalancer.py b/heat/tests/test_loadbalancer.py index 76d8074cb2..a4d956e844 100644 --- a/heat/tests/test_loadbalancer.py +++ b/heat/tests/test_loadbalancer.py @@ -21,13 +21,16 @@ import mox from nose.plugins.attrib import attr +from oslo.config import cfg from heat.common import exception from heat.common import context from heat.common import template_format +from heat.common import identifier from heat.engine import parser from heat.engine.resources import instance from heat.engine.resources import user from heat.engine.resources import loadbalancer as lb +from heat.engine.resources import wait_condition as wc from heat.engine.resource import Metadata from heat.engine.resources import stack from heat.tests.v1_1 import fakes @@ -35,7 +38,7 @@ from heat.tests import fakes as test_fakes def create_context(mocks, user='lb_test_user', - tenant='test_admin', ctx=None): + tenant='test_tenant', ctx=None): ctx = ctx or context.get_admin_context() mocks.StubOutWithMock(ctx, 'username') mocks.StubOutWithMock(ctx, 'tenant_id') @@ -57,6 +60,9 @@ class LoadBalancerTest(unittest.TestCase): self.fkc = test_fakes.FakeKeystoneClient( username='test_stack.CfnLBUser') + cfg.CONF.set_default('heat_waitcondition_server_url', + 'http://127.0.0.1:8000/v1/waitcondition') + def tearDown(self): self.m.UnsetStubs() print "LoadBalancerTest teardown complete" @@ -93,6 +99,9 @@ class LoadBalancerTest(unittest.TestCase): self.m.StubOutWithMock(user.AccessKey, 'keystone') user.AccessKey.keystone().MultipleTimes().AndReturn(self.fkc) + self.m.StubOutWithMock(wc.WaitConditionHandle, 'keystone') + wc.WaitConditionHandle.keystone().MultipleTimes().AndReturn(self.fkc) + lb.LoadBalancer.nova().AndReturn(self.fc) instance.Instance.nova().MultipleTimes().AndReturn(self.fc) self.fc.servers.create( @@ -101,15 +110,18 @@ class LoadBalancerTest(unittest.TestCase): scheduler_hints=None, userdata=mox.IgnoreArg(), security_groups=None, availability_zone=None).AndReturn( self.fc.servers.list()[1]) - #stack.Stack.create_with_template(mox.IgnoreArg()).AndReturn(None) Metadata.__set__(mox.IgnoreArg(), mox.IgnoreArg()).MultipleTimes().AndReturn(None) lb.LoadBalancer.nova().MultipleTimes().AndReturn(self.fc) + + self.m.StubOutWithMock(wc.WaitConditionHandle, 'get_status') + wc.WaitConditionHandle.get_status().AndReturn(['SUCCESS']) self.m.ReplayAll() t = self.load_template() s = self.parse_stack(t) + resource = self.create_loadbalancer(t, s, 'LoadBalancer') hc = {