From f5dfdff4b8eedc25af8c329ecc5e5490aec9a5ff Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Thu, 13 Sep 2012 20:56:48 +0200 Subject: [PATCH] tests: Fail promptly on stack creation failure Fix the functional tests to report failure as soon as stack creation fails, rather than waiting 80+ minutes to time out. Change-Id: Ie48a84c7bb3ab274337297cc740b78d58d8ed4a6 Signed-off-by: Zane Bitter --- ..._WordPress_Single_Instance_With_EBS_EIP.py | 2 +- ...test_WordPress_Single_Instance_With_EIP.py | 2 +- heat/tests/functional/util.py | 54 +++++++++++++------ 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/heat/tests/functional/test_WordPress_Single_Instance_With_EBS_EIP.py b/heat/tests/functional/test_WordPress_Single_Instance_With_EBS_EIP.py index dd6e9375..51cd8b66 100644 --- a/heat/tests/functional/test_WordPress_Single_Instance_With_EBS_EIP.py +++ b/heat/tests/functional/test_WordPress_Single_Instance_With_EBS_EIP.py @@ -54,7 +54,7 @@ class WordPressEBSEIPFunctionalTest(unittest.TestCase): found = 0 mylist = nclient.floating_ips.list() for item in mylist: - if item.instance_id == self.stack.phys_rec_id: + if item.instance_id == self.stack.instance_phys_ids()[0]: print 'floating IP found', item.ip found = 1 break diff --git a/heat/tests/functional/test_WordPress_Single_Instance_With_EIP.py b/heat/tests/functional/test_WordPress_Single_Instance_With_EIP.py index e175443d..6e189a2e 100644 --- a/heat/tests/functional/test_WordPress_Single_Instance_With_EIP.py +++ b/heat/tests/functional/test_WordPress_Single_Instance_With_EIP.py @@ -54,7 +54,7 @@ class WordPressEIPFunctionalTest(unittest.TestCase): found = 0 mylist = nclient.floating_ips.list() for item in mylist: - if item.instance_id == self.stack.phys_rec_id: + if item.instance_id == self.stack.instance_phys_ids()[0]: print 'floating IP found', item.ip found = 1 break diff --git a/heat/tests/functional/util.py b/heat/tests/functional/util.py index a16e6dae..62c880ff 100644 --- a/heat/tests/functional/util.py +++ b/heat/tests/functional/util.py @@ -327,19 +327,14 @@ class Stack(object): alist = None tries = 0 + print 'Waiting for stack creation to be completed' - while not alist: + while self.in_state('CREATE_IN_PROGRESS'): tries += 1 assert tries < 500 time.sleep(10) - events = self.heatclient.list_stack_events(**parameters) - root = etree.fromstring(events) - alist = root.xpath('//member[StackName="' + self.stackname + - '" and ResourceStatus="CREATE_COMPLETE" \ - and ResourceType="AWS::EC2::Instance"]') - elem = alist.pop() - self.phys_rec_id = elem.findtext('PhysicalResourceId') + assert self.in_state('CREATE_COMPLETE') # during nose test execution this file will be imported even if # the unit tag was specified @@ -368,6 +363,13 @@ class Stack(object): glanceclient = None heatclient = None + def in_state(self, state): + stack_list = self.heatclient.list_stacks(StackName=self.stackname) + root = etree.fromstring(stack_list) + xpq = '//member[StackName="%s" and StackStatus="%s"]' + alist = root.xpath(xpq % (self.stackname, state)) + return bool(alist) + def cleanup(self): parameters = {'StackName': self.stackname} c = self.get_heat_client() @@ -445,6 +447,16 @@ class Stack(object): value = output.findtext('OutputValue') return value + def instance_phys_ids(self): + events = self.heatclient.list_stack_events(StackName=self.stackname) + root = etree.fromstring(events) + xpq = ('//member[StackName="%s" and ' + 'ResourceStatus="CREATE_COMPLETE" and ' + 'ResourceType="AWS::EC2::Instance"]') + alist = root.xpath(xpq % self.stackname) + + return [elem.findtext('PhysicalResourceId') for elem in alist] + def response_xml_item(self, response, prefix, key): ''' Extract response item via xpath prefix and key name @@ -519,19 +531,12 @@ class StackBoto(Stack): alist = None tries = 0 print 'Waiting for stack creation to be completed' - while not alist: + while self.in_state('CREATE_IN_PROGRESS'): tries += 1 assert tries < 500 time.sleep(10) - events = self.heatclient.list_stack_events(**parameters) - alist = [e for e in events - if e.stack_name == self.stackname - and e.resource_status == "CREATE_COMPLETE" - and e.resource_type == "AWS::EC2::Instance"] - elem = alist.pop() - self.phys_rec_id = elem.physical_resource_id - print "CREATE_COMPLETE, physical_resource_id=%s" % self.phys_rec_id + assert self.in_state('CREATE_COMPLETE') # during nose test execution this file will be imported even if # the unit tag was specified @@ -560,6 +565,21 @@ class StackBoto(Stack): glanceclient = None heatclient = None + def in_state(self, state): + stack_list = self.heatclient.list_stacks(StackName=self.stackname) + this = [s for s in stack_list if s.stack_name == self.stackname][0] + return this.resource_status == state + + def instance_phys_ids(self): + events = self.heatclient.list_stack_events(StackName=self.stackname) + + def match(e): + return (e.stack_name == self.stackname and + e.resource_status == "CREATE_COMPLETE" and + e.resource_type == "AWS::EC2::Instance") + + return [e.physical_resource_id for e in events if match(e)] + def get_stack_output(self, output_key): ''' Extract a specified output from the DescribeStacks details -- 2.45.2